在 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
这是我使用 GAS 语法为 64 位英特尔汇编编写的代码示例。当代码为 运行 时,期望打印出字符串: 在 _print 子例程中。
#This example is a an example to call a subroutine
.global _start
.section .text
_start:
call _print
_exit:
#exit call
mov , %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
然后它完美地工作并且 none 的额外字符 (;
Q) 将被写入标准输出。
ali@alix2:~/Programming/asm/GAS-Syntax/SubRoutine$ ./subroutine
Inside the _print subroutine.
ali@alix2:~/Programming/asm/GAS-Syntax/SubRoutine$
谁能解释一下这背后的原因?谢谢
movq message_size, %rdx
是一个 64 位 (qword) 加载,包括 .byte 30
、.int 0x1
以及其后的 3 个字节。使用调试器(例如 GDB)查看寄存器中的值。并使用 strace ./subroutine
来跟踪系统调用并显示您正在向 write
.
传递一个巨大的长度
您可以使用 movzbl message_size(%rip), %edx
加载将该字节零扩展到 RDX。
或者更好的是,让 assembler 为您计算大小作为 assemble-时间常数
.equ message_size, . - message
所以你可以使用 $message_size
作为立即数。无需单独硬编码大小或将其存储在数据存储器中。
来电号码相同;不要为它加载 64 位,尤其是 32 位 .int
!如果在那之后 .data
中还有任何其他内容,它会将垃圾加载到 RAX 的高字节中。您 可以 只是 mov
到 EAX,它隐式地从零扩展到 RAX。
这是我使用 GAS 语法为 64 位英特尔汇编编写的代码示例。当代码为 运行 时,期望打印出字符串: 在 _print 子例程中。
#This example is a an example to call a subroutine
.global _start
.section .text
_start:
call _print
_exit:
#exit call
mov , %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
然后它完美地工作并且 none 的额外字符 (;
Q) 将被写入标准输出。
ali@alix2:~/Programming/asm/GAS-Syntax/SubRoutine$ ./subroutine
Inside the _print subroutine.
ali@alix2:~/Programming/asm/GAS-Syntax/SubRoutine$
谁能解释一下这背后的原因?谢谢
movq message_size, %rdx
是一个 64 位 (qword) 加载,包括 .byte 30
、.int 0x1
以及其后的 3 个字节。使用调试器(例如 GDB)查看寄存器中的值。并使用 strace ./subroutine
来跟踪系统调用并显示您正在向 write
.
您可以使用 movzbl message_size(%rip), %edx
加载将该字节零扩展到 RDX。
或者更好的是,让 assembler 为您计算大小作为 assemble-时间常数
.equ message_size, . - message
所以你可以使用 $message_size
作为立即数。无需单独硬编码大小或将其存储在数据存储器中。
来电号码相同;不要为它加载 64 位,尤其是 32 位 .int
!如果在那之后 .data
中还有任何其他内容,它会将垃圾加载到 RAX 的高字节中。您 可以 只是 mov
到 EAX,它隐式地从零扩展到 RAX。