Linux 在GAS中进行系统调用,并在.data部分中使用变量,并在另一个子例程中访问它们以进行系统调用
下面是我使用GAS语法为64位英特尔汇编编写的代码示例。当代码运行时,期望打印出_print子例程中的字符串Linux 在GAS中进行系统调用,并在.data部分中使用变量,并在另一个子例程中访问它们以进行系统调用,linux,assembly,x86-64,gnu-assembler,att,Linux,Assembly,X86 64,Gnu Assembler,Att,下面是我使用GAS语法为64位英特尔汇编编写的代码示例。当代码运行时,期望打印出_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:
#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$
但是当我不使用变量时,我将它改为
mov$30,%rdx
然后它就完美地工作了,所有额外的字符(;
Q)都不会再写入标准输出了
ali@alix2:~/Programming/asm/GAS-Syntax/SubRoutine$ ./subroutine
Inside the _print subroutine.
ali@alix2:~/Programming/asm/GAS-Syntax/SubRoutine$
有人能解释一下这背后的原因吗?谢谢。
movq message\u size,%rdx
是一个64位(qword)加载,包括.byte 30
和.int 0x1
,以及超过该值的3个字节。使用调试器(例如GDB)查看寄存器中的值。并使用strace./subroutine
跟踪系统调用,并显示您正在向write
传递一个很大的长度
您可以使用movzbl消息大小(%rip),%edx
load将该字节扩展为RDX
或者更好,让汇编器使用.eq消息大小,.-消息
,因此您可以使用$message\u size
作为即时消息。无需单独硬编码大小或将其存储在数据内存中
电话号码相同;不要为它执行64位加载,特别是不要从32位
.int
加载!如果在此之后.data
中还有其他内容,它会将垃圾加载到RAX的高位字节中。您可以将mov
插入EAX,其中零隐式扩展到RAX。如果您发现问题的格式不正确,请使用工具栏上的和“代码格式”按钮自行修复。谢谢,你是个明星。非常感谢您的帮助和指导。我知道如何在NASM中计算弦长,但我不知道如何在GAS中计算弦长。我试着查了一下,用谷歌搜索了几分钟,但没有什么乐趣。因此,如果你有一个链接到一个非常好的网站,描述气体语法和最佳实践,如果你能分享,我将非常感激。另外,如果你知道关于气体组装的好书,你能推荐一些给我吗?顺便说一句,我尝试了你的两个建议,它们都非常有效。但我更喜欢后者。再次感谢。@Alex:这是上游文档。查看编译器输出是学习at&T语法的另一种方法,尽管通常它们只是到处输出文字数字,因为它们不试图使源代码可维护。我不知道什么书;我知道从头开始的编程使用AT&T语法(在32位x86 Linux上),但它通常是在教授asm。有一些信息和链接。IDK如果是好的。