我是程序集的新手,正在尝试编写一个版本的"回声;内置,但一次只能操作1个字节。
我有以下内容,它按照我想要的方式工作,只是它在读取和写入时都溢出了超过1个字节,尽管我在两个系统调用中都明确表示x2中有1个字节。我做错了什么?
示例运行:
sh-4.2$ ./echo1b
f
f
o
o
b
b
bar
bar
bazbazbaz
bazbazbaz
q
sh-4.2$
这是代码:
.data
temp: .byte 1
.text
.globl _start
_start:
/* read one byte from stdin, store to temp */
mov x0, #0x0
adr x1, temp
mov x2, #0x1
mov x8, #0x3F
svc #0x0
/* write newline to stdout */
mov x0, #0x1
mov x1, #0xA
mov x2, #0x1
mov x8, #0x40
svc #0x0
/* if byte in temp is "q", exit */
mov x5, #0x71
ldr x1, temp
cmp x1, x5
beq exit
/* otherwise, write it to stdout and repeat */
mov x0, #0x1
adr x1, temp
mov x2, #0x1
mov x8, #0x40
svc #0x0
b _start
exit:
/* exit cleanly */
eor x0, x0, x0
eor x1, x1, x1
eor x2, x2, x2
mov x8, #0x5D
svc #0x0
您的代码中存在以下几个问题:
- 如注释中所述,当调用
sys_write
时,输出缓冲区的地址必须在x1
中,就像调用temp
一样 - 当比较
temp
和换行符时,必须使用ldrb w1, [x0]
而不是ldr x1, temp
,其中x0
指向temp
。后者将读取4个字节,而不能保证上面的三个字节为零
我还改进了您代码的某些部分:
cmp
可以与12位立即数一起使用,因此不需要将0x71
放入寄存器- 将第二个CCD_ 11调用移动到CCD_
sys_exit
仅使用x0
作为参数,因此不需要将x1
和x2
设置为零
这是在Raspbian 4.19上测试的最终代码(基于debian(:
.data
temp: .byte 1
newline: .byte 0x0A
.text
.globl _start
loop:
// 4: Otherwise, write it to stdout and repeat
mov x0, #0x1 // int fd
adr x1, temp // void* buf
mov x2, #0x1 // size_t count
mov x8, #0x40 // sys_write
svc #0x0
_start:
// 1: Read one byte from stdin and store to temp (including newline)
mov x0, #0x0 // int fd
adr x1, temp // void* buf
mov x2, #0x1 // size_t count
mov x8, #0x3F // sys_read
svc #0x0
// 2: If byte in temp is 'q', exit
adr x0, temp
ldrb w1, [x0] // instead of temp
cmp x1, #0x71
bne loop
// 5: Exit cleanly
eor x0, x0, x0 // int status
mov x8, #0x5D // sys_exit
svc #0x0
注释后编辑:要在退出时刷新stdin,可以在步骤5:之前添加以下行
// 5: Flush stdin (read until newline)
flush:
mov x0, #0x0 // int fd
adr x1, temp // void* buf
mov x2, #0x1 // size_t count
mov x8, #0x3F // sys_read
svc #0x0
adr x0, temp
ldrb w1, [x0]
cmp x1, #0x0A
bne flush // loop until x0 == 0x0A