在 GAS 中进行系统调用并在 .data 部分中使用变量并访问它们以在另一个子例程中进行系统调用
Posted
技术标签:
【中文标题】在 GAS 中进行系统调用并在 .data 部分中使用变量并访问它们以在另一个子例程中进行系统调用【英文标题】:Making a system call in GAS and using variables in .data section and accessing them for a system call inside another sub-routine 【发布时间】:2020-04-13 15:19:18 【问题描述】:这是我为 64 位英特尔汇编使用 GAS 语法编写的代码示例。当代码运行时,期望打印出字符串: 在 _print 子例程中。
#This example is a an example to call a subroutine
.global _start
.section .text
_start:
call _print
_exit:
#exit call
mov $60, %rax
xor %rdi, %rdi
syscall
_print:
#set up the stack frame
push %rbp
mov %rsp, %rbp
# write syscall's parameter set up
mov std_out_fd, %rdi
mov $message, %rsi
movq message_size, %rdx
mov write_syscall_no, %rax
syscall
#Restore callers registers value
#pop %rdx
#pop %rsi
#pop %rdi
#Destroy the stack frame:
mov %rbp, %rsp
pop %rbp
ret
.section .data
std_out_fd: .int 0x02
message: .ascii "Inside the _print subroutine.\n"
message_size: .byte 30
write_syscall_no: .int 0x01
==========================================
当我尝试使用声明的变量 'message_size' 作为 write 系统调用的第三个参数时,我在屏幕上打印消息后打印了一些奇怪的额外字符:
ali@alix2:~/Programming/asm/GAS-Syntax/SubRoutine$ as -o subroutine.o subroutine.s
ali@alix2:~/Programming/asm/GAS-Syntax/SubRoutine$ ld -o subroutine subroutine.o
ali@alix2:~/Programming/asm/GAS-Syntax/SubRoutine$ ./subroutine
Inside the _print subroutine.
`;`Qali@alix2:~/Programming/asm/GAS-Syntax/SubRoutine$
但是当我不使用变量时,我将其更改为 移动 $30, %rdx
然后它就可以完美运行,并且不会再将多余的字符(;
Q)写入标准输出。
ali@alix2:~/Programming/asm/GAS-Syntax/SubRoutine$ ./subroutine
Inside the _print subroutine.
ali@alix2:~/Programming/asm/GAS-Syntax/SubRoutine$
谁能解释这背后的原因?谢谢。
【问题讨论】:
如果您发现您的问题出现格式错误,请使用edit link 和工具栏上的代码格式按钮自行修复。谢谢。 【参考方案1】:movq message_size, %rdx
是一个 64 位 (qword) 加载,包括 .byte 30
和 .int 0x1
,以及之后的 3 个字节。使用调试器(例如 GDB)查看寄存器中的值。并使用strace ./subroutine
跟踪系统调用,并显示您正在向write
传递大量长度。
您可以使用 movzbl message_size(%rip), %edx
加载将该字节零扩展为 RDX。
或者更好的是,让汇编器使用.equ message_size, . - message
为您计算大小作为汇编时常量,这样您就可以将$message_size
用作立即数。无需单独对大小进行硬编码或将其存储在数据存储器中。
电话号码也一样;不要对其进行 64 位加载,尤其是不要从 32 位 .int
加载!如果在那之后.data
中有任何其他内容,它会将垃圾加载到 RAX 的高字节中。你可以只是mov
到 EAX 中,它会隐式地零扩展到 RAX。
【讨论】:
你是明星。非常感谢您的帮助和指导。我知道如何在 NASM 中计算字符串长度,但我不知道如何在 GAS 中进行。我试着查了一下,用谷歌搜索了几分钟,但没有任何乐趣。因此,如果您有一个非常好的描述 GAS 语法和最佳实践的网站的链接,如果您能分享,我将不胜感激。另外,如果你知道关于 GAS 组装的好书,你能推荐一些给我吗? 顺便说一句,我尝试了您的两个建议,它们都非常有效。但我更喜欢后一种。再次感谢。 @Alex: sourceware.org/binutils/docs/as 是上游文档。查看编译器输出是学习 AT&T 语法的另一种方法,尽管它们通常只是在各处输出文字数字,因为它们并没有试图制作可维护的源代码。我不知道任何书;我知道从头开始编程使用 AT&T 语法(在 32 位 x86 Linux 上),但它通常是在教授 asm。 ***.com/tags/att/info 有一些信息和链接。 IDK 如果en.wikibooks.org/wiki/X86_Assembly/GAS_Syntax 有什么好处。以上是关于在 GAS 中进行系统调用并在 .data 部分中使用变量并访问它们以在另一个子例程中进行系统调用的主要内容,如果未能解决你的问题,请参考以下文章
在 send() 调用内的“options”对象中不包括“gas”或“gasPrice”属性
x86-64 GAS Intel 语法中的 RIP 相对变量引用(如“[RIP + _a]”)如何工作?