学习汇编-echo程序名

发布于 2024-11-28 19:43:29 字数 684 浏览 1 评论 0原文

我正在尝试用汇编语言编写一个简单的程序来写出程序的名称。使用 gdb 进行调试,我确定对 sys_write 的调用返回 -14 (EFAULT)。我还能够验证我的 strlen 函数是否正常工作。似乎存在某种内存访问问题,但考虑到 strlen 正在访问相同的内存并且工作正常,我不明白可能出了什么问题。出了什么问题?

谢谢!

完整代码:

section .text
    global _start

_start:
    mov rax, [rsp+8]
    push rax
    call strlen
    add rsp, 8

    mov rdx, rax ; bytes to write
    mov rax, 4 ; sys_write
    mov rbx, 1 ; stdout
    mov rcx, [rsp+8] ; addr of string
    int 0x80

    ; exit
    mov rax, 1
    mov rbx, 0
    int 0x80

strlen:
    mov rax, 0
    mov rbx, [rsp+8]
strlen_loop:
    cmp byte [rbx+rax], 0
    je strlen_end
    inc rax
    jmp strlen_loop
strlen_end:
    ret ; len in rax

I am trying to write a simple program in assembly that will write out the name of the program. Using gdb to debug, I've determined that the call to sys_write is returning -14 (EFAULT). I've also been able to verify that my strlen function is working correctly. It seems like there is some sort of memory access issue, but I don't understand what could be wrong given that strlen is accessing the same memory and working fine. What is going wrong?

Thanks!

The full code:

section .text
    global _start

_start:
    mov rax, [rsp+8]
    push rax
    call strlen
    add rsp, 8

    mov rdx, rax ; bytes to write
    mov rax, 4 ; sys_write
    mov rbx, 1 ; stdout
    mov rcx, [rsp+8] ; addr of string
    int 0x80

    ; exit
    mov rax, 1
    mov rbx, 0
    int 0x80

strlen:
    mov rax, 0
    mov rbx, [rsp+8]
strlen_loop:
    cmp byte [rbx+rax], 0
    je strlen_end
    inc rax
    jmp strlen_loop
strlen_end:
    ret ; len in rax

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

嘿嘿嘿 2024-12-05 19:43:29

正如我在评论中所写,x86_64 使用与 32 位 Linux 不同的系统调用方法。特别是 int $0x80 不再是执行此操作的方法(尽管如果您安装了 32 位库,它可能会半工作......)。例如,请参阅之前的讨论

在 32 位 x86 上,您应该执行以下操作:

mov eax, SYSCALL_NUMBER
mov ebx, first_param
mov ecx, second_param
mov edx, third_param
int 0x80

您应该在 x86_64 上执行以下操作:

mov rax, SYSCALL_NUMBER_64 ; This is usually different from the 32-bit version!
mov rdi, first_param
mov rsi, second_param
mov rdx, third_param
syscall

要打印程序名称,请将程序更改为以下内容,它应该可以工作。对于其他对启动时程序环境的外观感兴趣的人,请参阅此处

section .text
    global _start

_start:
    mov rax, [rsp+8]
    push rax
    call strlen
    add rsp, 8

    mov rdi, 1 ; fd = stdout
    mov rsi, [rsp+8] ; buf = addr to string
    mov rdx, rax ; count = strlen(string)
    mov rax, 1 ; write
    syscall

    mov rdi, 0 ; status = 0
    mov rax, 60 ; exit
    syscall

strlen:
    mov rax, 0
    mov rbx, [rsp+8]
strlen_loop:
    cmp byte [rbx+rax], 0
    je strlen_end
    inc rax
    jmp strlen_loop
strlen_end:
    ret ; len in rax

编译使用:

nasm -g -f elf64 -o sc.o sc.asm
gcc -nostartfiles -o sc sc.o

As I wrote in a comment, x86_64 uses a different method for syscalls than 32-bit linux. In particular int $0x80 is no longer the way to do it (though it might semi-work if you have the 32-bit libraries installed....). See for instance this previous discussion.

Where on 32-bit x86 you would do:

mov eax, SYSCALL_NUMBER
mov ebx, first_param
mov ecx, second_param
mov edx, third_param
int 0x80

You should do the following on x86_64:

mov rax, SYSCALL_NUMBER_64 ; This is usually different from the 32-bit version!
mov rdi, first_param
mov rsi, second_param
mov rdx, third_param
syscall

To print the program name, change your program to the following and it should work. For anyone else interested in how the program environment looks on startup, see here.

section .text
    global _start

_start:
    mov rax, [rsp+8]
    push rax
    call strlen
    add rsp, 8

    mov rdi, 1 ; fd = stdout
    mov rsi, [rsp+8] ; buf = addr to string
    mov rdx, rax ; count = strlen(string)
    mov rax, 1 ; write
    syscall

    mov rdi, 0 ; status = 0
    mov rax, 60 ; exit
    syscall

strlen:
    mov rax, 0
    mov rbx, [rsp+8]
strlen_loop:
    cmp byte [rbx+rax], 0
    je strlen_end
    inc rax
    jmp strlen_loop
strlen_end:
    ret ; len in rax

Compiled using:

nasm -g -f elf64 -o sc.o sc.asm
gcc -nostartfiles -o sc sc.o
谎言 2024-12-05 19:43:29

您在开头添加 rsp 和 8,导致 sys_write 调用获取 strlen 函数之外的另一个字符串。 strlen 不会改变堆栈,并且推送的 rax 以后不会使用?为什么不删除 push raxadd rsp, 8 语句,看看它对您有何作用?

You add rsp with 8 at the beginning causing the sys_write call to get another string than your strlen function. The strlen does not alter the stack and the pushed rax is not used later? Why don't you drop the push rax and add rsp, 8 statements and see how that works our for you?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文