Linux 在GAS中进行系统调用,并在.data部分中使用变量,并在另一个子例程中访问它们以进行系统调用

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:

下面是我使用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:
    #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如果是好的。