Making a system call in GAS and using variables in .data section and accessing them for a system call inside another sub-routine

筅森魡賤 提交于 2020-08-10 20:47:27

问题


Here is the code example that I have written using GAS syntax for 64 bit intel assembly. When the code is run the expectation is to print out the string: Inside the _print subroutine.

#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

=========================================

When I try to use the declared variable 'message_size' as the third parameter for the write system call I get a few weird extra characters printed after the message is printed on the screen:

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$

but when instead of using the variable I change it to mov $30, %rdx

then it works perfectly and none of the extra characters(;Q) will be written to stdout anymore.

ali@alix2:~/Programming/asm/GAS-Syntax/SubRoutine$ ./subroutine
Inside the _print subroutine.
ali@alix2:~/Programming/asm/GAS-Syntax/SubRoutine$ 

Could anyone explain the reason behind this? Thanks.


回答1:


movq message_size, %rdx is a 64-bit (qword) load that include the .byte 30, and the .int 0x1, and 3 bytes past that. Use a debugger (GDB for example) to look at values in registers. And use strace ./subroutine to trace system calls and show that you're passing a huge length to write.

You could use a movzbl message_size(%rip), %edx load to zero-extend that byte into RDX.

Or better, let the assembler calculate sizes for you as assemble-time constants with
.equ message_size, . - message
so you can use $message_size as an immediate. No need to hard-code the size separately or to store it in data memory.

Same for the call number; don't do a 64-bit load for it, especially not from a 32-bit .int! If you had any other stuff in .data after that, it would load garbage into the high bytes of RAX. You could just mov into EAX which zero-extends into RAX implicitly.



来源:https://stackoverflow.com/questions/61191024/making-a-system-call-in-gas-and-using-variables-in-data-section-and-accessing-t

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!