Assembly 如何使用write系统调用打印整数?
这是一个从系统时钟创建随机数字的简单项目。它接受一个数字,将其转换为一个数字,然后加上48,使其在ASCII表中匹配。我的问题是它没有打印任何东西。从我可以说,它需要是一个字符串,甚至考虑打印。有什么方法可以让我“投”出来吗?是的,我知道,它是一个整数,但是假装它在ascii表上?这是我的代码供参考。除“prnt_时钟”外,一切正常。最后一件事,我不能使用任何C代码/函数,所以不,我不能使用printfAssembly 如何使用write系统调用打印整数?,assembly,raspberry-pi,arm,raspbian,Assembly,Raspberry Pi,Arm,Raspbian,这是一个从系统时钟创建随机数字的简单项目。它接受一个数字,将其转换为一个数字,然后加上48,使其在ASCII表中匹配。我的问题是它没有打印任何东西。从我可以说,它需要是一个字符串,甚至考虑打印。有什么方法可以让我“投”出来吗?是的,我知道,它是一个整数,但是假装它在ascii表上?这是我的代码供参考。除“prnt_时钟”外,一切正常。最后一件事,我不能使用任何C代码/函数,所以不,我不能使用printf .global rand .equ STDOUT, 1 .equ WRITE,
.global rand
.equ STDOUT, 1
.equ WRITE, 4
rand:
PUSH {LR}
BL get_clock
LDR R1, =time
ADD R1, R1, #5
LDRB R0, [R1]
BL num_to_digit
ADD R0, R0, #48
MOV R1, R0
BL prnt_clock
B rand_leave
get_clock:
MOV R7, #78 @ Get time of day
LDR R0, =time @ address of holder for time_t
MOV R1, #0 @ time zone not needed
SWI 0
MOV PC, LR
// Assumes the number is in R0
num_to_digit:
CMP R0, #9 @ Compare num to 9
SUBGT R0, R0, #10 @ If greater than, substract 10
BGT num_to_digit @ Repeat until its eq or lower than 9
MOV PC, LR @ Comeback to main
prnt_clock:
MOV R0, #STDOUT @ Print to terminal
MOV R2, #1 @ Print only the digit
MOV R7, #WRITE @ Write Syscall
@MOV R3, #0 @ Create a counter
SWI 0
rand_leave:
POP {LR}
MOV PC, LR
.data
time: .space 9
通常,使用printf或其他库打印整数 如果您正在寻找独立程序,请使用编译器编译C以获得程序集输出:
/*
r3 = magic division number
r2 = division
r0 = integer to be converted
*/
.syntax unified
.equ division, 0x66666667 // 1717986919; (2 ^ 34 + 6) / 10
.section .text
.global _start
_start:
push {ip}
mov r1, #0x0a // 10; newline
push {r1}
mov r7, #0x04 // write syscall
/*
If your architecture is ARMv7 (or above).
movw r3, #:lower16:division // 26215
movt r3, #:upper16:division // 26214
*/
ldr r3, =division
mov r0, #(0x01 << 0x1e) // replace this
_division:
smmul r1, r0, r3
asr r2, r1, #0x02
_modulo:
add r1, r2, r1, lsr #0x1f // 31
add r1, r1, r1, lsl #0x02
sub r0, r0, r1, lsl #0x01
_string:
add r0, #0x30 // 48; '0'
push {r0}
_shift:
mov r0, r2
cmp r0, #0x00
bne _division
_write:
mov r1, sp
ldr r3, [r1]
cmp r3, #0x00
beq _end
mov r0, #0x01 // stdout file descriptor
pop {ip}
mov r2, #0x01 // length
swi 0x00 // execute syscall
bne _write
_end:
pop {ip}
mov r7, #0x01 // exit syscall
mov r0, #0x00 // exit status
swi 0x00 // execute syscall
/*
r3=幻数
r2=除法
r0=要转换的整数
*/
.语法统一
.equ分部,0x666667//1717986919;(2 ^ 34 + 6) / 10
.第节.正文
.全球启动
_开始:
推送{ip}
mov r1#0x0a//10;新线
推送{r1}
mov r7,#0x04//写入系统调用
/*
如果您的体系结构是ARMv7(或更高版本)。
movw r3,#:较低16:分区//26215
移动r3,#:上16:分区//26214
*/
ldr r3,=除法
mov r0,#(0x01您需要存储整数(ascii字符)在内存中并传递它的地址。参见man 2写入。那么我如何将它存储在内存中呢?我是否制作了一个充满空格的标签asciz,然后将其存储在内存中?我真的不知道我该怎么做。我尝试了STR和LDR。但我找不到将整数存储在内存中的方法/是的,分配一个静态缓冲区会起作用。它不必是zero终止,如果它是一个单个数字(字符),您可以使用STRB
。您也可以将其推送到堆栈并传递其地址(但之后不要忘记清理它).对于除数/余数,重复减法是一种非常慢的算法,特别是对于像10这样的小除数。有关C算法和x86 Linux asm实现,请参阅。您可以编译C以获得ARM代码,并将堆栈空间缓冲区处理从我的x86 asm调整到ARM。如果您有代码要共享,特别是如果您编写它只是为了这个答案,直接将它包含在你的答案中(在一个带有三个反勾号的代码块中),而不是通过链接。(尤其是非现场链接;如果问题本身不应该作为副本关闭,那么链接其他问答是可以的。)是的,我的想法是:“我不断更新github repo,所以我可能会链接它。”但是我没有意识到我可以同时包含这两个。哦,是的,你仍然可以包含一个链接,并且注意,只要你在这里包含代码,它可能比答案更为最新。是的,我编辑了它=)ldr r1,=如果你使用不同的寄存器,除法可以从循环中提升出来,特别是如果您在缓冲区中生成一个字符串,并在整个过程中调用write
一次,如中的C。然后,直到最后一次,您才需要将系统调用参数放入regs中。