Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 如何使用汇编语言打印从1到n的数字?_Assembly_Raspberry Pi_Arm_Qemu - Fatal编程技术网

Assembly 如何使用汇编语言打印从1到n的数字?

Assembly 如何使用汇编语言打印从1到n的数字?,assembly,raspberry-pi,arm,qemu,Assembly,Raspberry Pi,Arm,Qemu,我不熟悉汇编语言,我正在尝试使用汇编语言打印1到n个数字,而不使用C库。我正在使用qemu作为raspberry pi的模拟器 下面是我尝试过的示例代码 .global _start _start: MOV R7, #3 @ Syscall read from keyboard MOV R0, #0 @ Input stream keyboard MOV R2, #1 @ Read 1 characters LDR R1, =character @ Put number in R1 M

我不熟悉汇编语言,我正在尝试使用汇编语言打印1到n个数字,而不使用C库。我正在使用qemu作为raspberry pi的模拟器

下面是我尝试过的示例代码

    .global _start
_start:
MOV R7, #3 @ Syscall read from keyboard
MOV R0, #0 @ Input stream keyboard
MOV R2, #1  @ Read 1 characters
LDR R1, =character @ Put number in R1
MOV R6,R1 @Holding value of R1 i.e. the input number 'n'
MOV R1,#0 @initialiing value 
MOV R2, #1 @counter
SWI 0

_loop:
AND R1, R1, R2 @Add one to each value of R1
B _write @print the value
SWI 0


_write:
MOV R7,#4 @ Syscall for output
MOV R0,#1 @ Output stream for R1
MOV R2,#1
CMP R1,R6 @Compare if the value is equal to 'n'
BNE _loop @if less than, then add again and print
SWI 0

end:
MOV R7,#1
SWI 0

.data
character:
.word 0
请让我知道,应该怎么做


谢谢

我注意到有几件事不对。调用例程(
SWI
)时,可以更改寄存器,因此您应该将值保存在正在使用的寄存器中(
push{r1,r2,r6,lr}
),并在例程(
pop{r1,r2,r6,lr}
)之后恢复它们,预期是r1和r2。
指令不是一个好的加法器,请使用
add
。在
\u循环中:
有一条额外的
SWI 0
指令。在
\u write:
寄存器
r1
中需要有
字符的地址,并且要写入的数据需要在内存中标记为
字符
,作为可打印字符(0x00000001不是可打印字符,添加0x30或十进制48将使其成为可打印字符)

我对你程序的修改是小写的。我在顶部添加了
main
,以防您希望使用
gdb
。我跳过/绕过输入并硬编码输入

    .global _start
main:
_start:
@MOV R7, #3 @ Syscall read from keyboard
@MOV R0, #0 @ Input stream keyboard
@MOV R2, #1  @ Read 1 characters
@LDR R1, =character @ Put number in R1
@MOV R6,R1 @Holding value of R1 i.e. the input number 'n'
@MOV R1,#0 @initialiing value
@MOV R2, #1 @counter
@SWI 0
mov  r6, #5
mov  r1, #0
mov  r2, #1

_loop:
@AND R1, R1, R2 @Add one to each value of R1
add  r1, r1, r2
B _write @print the value
@SWI 0


_write:
push {r1, r2, r6, lr}
add  r3, r1, #48
ldr  r0, =character
str  r3, [r0]
MOV R7,#4 @ Syscall for output
MOV R0,#1 @ Output stream for R1
ldr r1, =character
MOV R2,#1
SWI 0
pop {r1, r2, r6, lr}
CMP R1,R6 @Compare if the value is equal to 'n'
BNE _loop @if less than, then add again and print

end:
MOV R7,#1
SWI 0

.data
character:
.word 0
装配、连接和输出

as -o count2.o count2.s
ld -o count2 count2.o
./count2
12345
补充:

我还没有使用QEMU,但我认为问题可能是对内存的访问。试试这个,看看有没有什么不同。我还更改了
push
pop
指令

    .global _start
_start:
@MOV R7, #3 @ Syscall read from keyboard
@MOV R0, #0 @ Input stream keyboard
@MOV R2, #1  @ Read 1 characters
@LDR R1, =character @ Put number in R1
@MOV R6,R1 @Holding value of R1 i.e. the input number 'n'
@MOV R1,#0 @initialiing value
@MOV R2, #1 @counter
@SWI 0
mov  r6, #5
mov  r1, #0
mov  r2, #1

_loop:
@AND R1, R1, R2 @Add one to each value of R1
add  r1, r1, r2
B _write @print the value
@SWI 0


_write:
@push {r1, r2, r6, lr}
stmdb sp!, {r1, r2, r6, lr}
add  r3, r1, #48
@ldr  r0, =character
ldr  r0, character_address
str  r3, [r0]
MOV R7,#4 @ Syscall for output
MOV R0,#1 @ Output stream for R1
@ldr r1, =character
ldr r1, character_address
MOV R2,#1
SWI 0
@pop {r1, r2, r6, lr}
ldmia sp!, {r1, r2, r6, lr}
CMP R1,R6 @Compare if the value is equal to 'n'
BNE _loop @if less than, then add again and print

end:
MOV R7,#1
SWI 0

character_address:
.word character

.data
character:
.word 0

你需要解释你的程序实际上做了什么,而不仅仅是它应该做什么。它能装配吗?它会崩溃吗?它打印的是什么而不是你想要的吗?试着运行
strace./a.out
来跟踪系统调用,或者在gdb下运行它。你被困在哪里了?上面的程序不工作,它应该接受一个输入n,并连续打印出从0到n的所有值。例如:如果我输入5,它将打印12345。我搜索了很多,但我无法找出问题所在。有什么例子我可以看一下吗?你有没有在ARM EABI中注册Linux系统调用clobber的参考资料?在大多数平台上,Linux系统调用clobber的寄存器尽可能少(通常只调用返回值,但x86-64也会调用clobber
rcx
r11
,因为
syscall
不可避免)。如果ARM Linux EABI关闭其所有输入寄存器,我会感到惊讶,但这当然是可能的。如果你还是要把寄存器推到堆栈中,你最好只传递字符的堆栈地址,而不是使用静态位置。@Peter Cordes第14页给出了ARM寄存器的使用指南。寄存器r0-r3的风险最大。这是函数调用约定。它没有提到SWI,并指出它不是完整的ABI(在该文档中搜索“linux”)。您应该期望它们是不同的,因为例如i386 Linux(System V psABI)在函数调用上会对
eax
ecx
、和
edx
,但在系统调用上只会对
eax
(带返回值)。嗨!我在运行上述代码时遇到了分段错误。是你干的吗?