如何在汇编中将 RAX 中的值写入 STDOUT?
我可以使用 syscall 进行 write 将内存中的一些数据打印到 STDOUT:
ssize_t write(int fd, const void *buf, size_t count);
也就是说:
movq $1, %rax
movq $1, %rdi
move address_of_variable %rsi
movq $5, %rdx
syscall
但是如何打印寄存器值?
更新
.text
call start
start:
movq $100, %rdi
movq $10, %rsi
call print_number
ret
buffer:
.skip 64
bufferend:
# rdi = number
# rsi = base
print_number:
leaq bufferend, %rcx
movq %rdi, %rax
1:
xorq %rdx, %rdx
divq %rsi
add $'0', %dl
cmp $'9', %dl
jbe 2f
add $'A'-'0'-10, %dl
2:
sub $1, %rcx
mov %dl, (%rcx)
and %rax, %rax
jnz 1b
mov %rcx, %rsi
lea bufferend, %rdx
sub %rcx, %rdx
movq $1, %rax
movq $1, %rdi
syscall
ret
I can use syscall for write to print some data in memory to STDOUT:
ssize_t write(int fd, const void *buf, size_t count);
That is:
movq $1, %rax
movq $1, %rdi
move address_of_variable %rsi
movq $5, %rdx
syscall
But how can I print register values?
UPDATE
.text
call start
start:
movq $100, %rdi
movq $10, %rsi
call print_number
ret
buffer:
.skip 64
bufferend:
# rdi = number
# rsi = base
print_number:
leaq bufferend, %rcx
movq %rdi, %rax
1:
xorq %rdx, %rdx
divq %rsi
add
0', %dl
cmp
9', %dl
jbe 2f
add
A'-'0'-10, %dl
2:
sub $1, %rcx
mov %dl, (%rcx)
and %rax, %rax
jnz 1b
mov %rcx, %rsi
lea bufferend, %rdx
sub %rcx, %rdx
movq $1, %rax
movq $1, %rdi
syscall
ret
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您必须先将其转换为文本。您可以走简单的路线,使用 libc 中的
printf
,或者,如果您愿意,可以编写自己的转换实用程序。更新:如果您希望代码与位置无关,那么使用堆栈会更容易。简单地将缓冲区移动到代码段中,因为您在注释中链接到的代码不再起作用,因为现代处理器将代码段设为只读。我已经更新了代码以使用堆栈进行临时存储。
相反,如果您想将缓冲区实际存储在代码段中,这是可以完成的。您必须使用例如
mprotect(2)
将buffer
所在的页面标记为可写。这里在汇编中没有进行错误检查(并假设sysconf(_SC_PAGE_SIZE) == 4096
):现在,即使缓冲区位于代码段中,代码也应该可以工作。顺便说一句,我在示例中使用 sys_exit ,因为我正在使用 gcc xs -nostdlib -ggdb -o x 将其作为独立文件进行测试。
Update2:要在代码重定位时使用它,请使用 RIP 相对寻址。将
bufferend
更改为bufferend(%rip)
。You have to convert it to text first. You can go the easy route and use e.g.
printf
from libc or, if you're so inclined, write your own conversion utility.Update: If you want the code to be position independent it's easier to use the stack. Simply moving the buffer into the code segment as the code you linked to in the comments doesn't work anymore since modern processors have code segments as read only. I have updated the code to use the stack for temporary storage.
If, perversely, you want to actually store the buffer in the code segment it can be done. You have to mark the page where
buffer
resides as writable using e.g.mprotect(2)
. Here done without error checking (and assumingsysconf(_SC_PAGE_SIZE) == 4096
) in assembly:And now the code should work even when the buffer is located in the code segment. BTW I use sys_exit in my example because I'm testing it as a stand alone file with
gcc x.s -nostdlib -ggdb -o x
.Update2: To use it when the code is relocated use RIP-relative addressing. Change
bufferend
tobufferend(%rip)
.您不能编写纯数字(因为它们将被解释为指针),您需要将该数字转换为字符串并将指针作为
write
的参数传递给该字符串。类似于这个的东西。you can't write pure numbers (as they will be interpreted as pointers), you need to convert that number to a string and pass the pointer to that string as an arg of
write
. something along the lines of this.