在 64 位汇编臂中捕获输入 mac os

Capture input in assembly arm 64 bit mac os

正在尝试从用户输入中捕获两个字符和换行符。

程序将 3 个地狱世界打印到屏幕上,然后用户可以输入一些字符。 一切似乎都有效,但它不打印输入

我怀疑是我在_read函数中对X1寄存器的操作方式,或者buffer的分配方式造成的

运行编译代码时没有报错。

代码是使用以下命令编译的。它应该 运行 在 Mac M1

as HelloWorld.s -o HelloWorld.o && ld -macosx_version_min 12.0.0 -o HelloWorld HelloWorld.o -lSystem -syslibroot `xcrun -sdk macosx --show-sdk-path` -e _start -arch arm64 && ./HelloWorld

//HelloWorld.s

.equ SYS_WRITE, 4
.equ SYS_READ, 3
.equ NEWLN, 10


.global _start             // Provide program starting address to linker
.align 2

// Setup the parameters to print hello world
// and then call Linux to do it.

_start: 
        adr X4, helloworld1
        mov X1, X4
        bl _sizeof
        bl _print

        adr X4, helloworld2
        mov X1, X4
        bl _sizeof                
        bl _print


        adr X4, helloworld3
        mov X1, X4
        bl _sizeof
        bl _print


        bl _read
        //mov X2, 4
       // bl _sizeof
        bl _print


_exit:
        mov     X0,  X2     // Use 0 return code
        mov     X16, #1     // Service command code 1 terminates this program
        svc     0           // Call MacOS to terminate the program





_sizeof: //X1 = address, X2 = out length, string must terminate with \n
        str LR, [SP, #-16]!     //Store registers
        //str W0, [SP, #-16]!


        mov X2, #0
        __loop:
             
                ldrb W0, [X1, X2]       //load a byte into W0 (32 bit)
                add X2, X2, #1          //Add 1 offset  
                cmp W0, NEWLN             //Compare byte with \n return
                bne __loop

        //ldr W0, [SP], #16
        ldr LR, [SP], #16       //Load registers
        ret




_print: //X2 = length, X1 = address
        str LR, [SP, #-16]!     //Store registers

        mov X0, #1     // 1 = StdOut
       // mov X1, X1      // string to print
       // mov X2, X2     // length of string
        mov X16, SYS_WRITE     // MacOS write system call
        svc 0     // Call kernel to output the string
        
        ldr LR, [SP], #16       //Load registers
        ret  

_read:
//3 AUE_NULL    ALL { user_ssize_t read(int fd, user_addr_t cbuf, user_size_t nbyte); } 

        str LR, [SP, #-16]!     //Store registers
        
        adr X1, msg

        mov X0, #0    // 0 = StdIn
        ldr X1, [x1]    // address to store string

        mov X2, #4     // length 
        mov X16, SYS_READ     // MacOS read system call
        svc 0     // Call system

        ldr LR, [SP], #16       //Load registers
        ret

msg: .ds 4     //memory buffer for keyboard input


helloworld1:      .ascii  "Hello World\n"
helloworld2:      .ascii  "Happy new year for 2022\n"
helloworld3:      .ascii  "Welcome to AARCH64 assembly on Mac Silicon\n"

首先你需要移动msg到一个可写段:

.data
msg: .ds 4     //memory buffer for keyboard input

.text // keep everything else in __TEXT

然后,因为段可能会在 link 时间任意移动,Apple 的工具链将不再允许您使用 adr 来获取该缓冲区的地址 - 您将不得不使用adrpadd:

adrp x1, msg@page
add x1, x1, msg@pageoff

如果需要,您可以告诉 link 人员请尽可能将其优化回 adr

Lloh0:
    adrp x1, msg@page
Lloh1:
    add x1, x1, msg@pageoff
.loh AdrpAdd Lloh0, Lloh1

然后你需要删除这一行:

ldr X1, [x1]

这将加载缓冲区的内容,它只是空字节。

最后,您应该将 x0 值更改为 exit 为常量:

mov x0, 0

此时 x2 中的值将被破坏,您也不需要它。