assembly 捕获汇编arm 64位mac os中的输入

ds97pgxw  于 2023-01-09  发布在  Mac
关注(0)|答案(2)|浏览(175)

尝试从用户输入中捕获两个字符和新行。
这个程序把3个helloworld打印到屏幕上,然后用户可以输入一些字符。一切看起来都正常,但是它不打印输入
我怀疑这是由于我在_read函数中操作X1寄存器的方式,或者是分配缓冲区的方式
运行代码时不报告任何错误。
代码是使用以下命令编译的。它应该在MacM1上运行

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"
4xy9mtcn

4xy9mtcn1#

首先,您需要将msg移动到一个可写段:

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

.text // keep everything else in __TEXT

然后,由于段可以在链接时任意移动,苹果的工具链将不再允许您使用adr来获取该缓冲区的地址-您将不得不使用adrpadd

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

如果需要,可以告诉链接器尽可能将其优化回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中的值将被删除,您也不需要它。

2ic8powd

2ic8powd2#

作为一个参考,任何人在未来寻找一个例子,从标准在苹果硅(M1)阅读,这段代码(基于上述信息)的工作。它接受一个字符串多达20个字符,并打印出来的标准输出。

.global _start
.align 2

_start: 
    mov X16, 3
    mov X0, 0
    mov X2, 20
    adrp    x1, msg@page
    add x1, x1, msg@pageoff
    svc 0

_write:
    mov X16, 4
    mov X0, 1
    adrp    x1, msg@page
    add x1, x1, msg@pageoff
    svc 0

_end:
    mov X0, 0
    mov X16, 1
    svc 0

.data
msg:
    .ds 20

您的makefile应该如下所示:

temp: temp.o
    ld -o temp temp.o -lSystem -syslibroot `xcrun -sdk macosx --show-sdk-path` -e _start -arch arm64 

temp.o: temp.s
    as -arch arm64 -o temp.o temp.s

相关问题