学习汇编 - 回声程序名称 [英] Learning assembly - echo program name

查看:205
本文介绍了学习汇编 - 回声程序名称的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想写组装一个简单的程序,将写出来的程序的名称。使用GDB调试,我已经确定调用SYS_WRITE将返回-14(EFAULT)。我也能验证我的strlen函数是否正常工作。好像有某种内存访问问题,但我不明白是什么可能是错误的假定的strlen正在访问相同的内存和做工精细。这是怎么回事了?

谢谢!

满code:

  .text段
    全球_start_开始:
    RAX MOV [RSP + 8]
    推RAX
    调用strlen
    加RSP,8    MOV RDX,RAX;要写入的字节
    MOV RAX,4; SYS_WRITE
    MOV RBX,1;标准输出
    RCX MOV [RSP + 8];字符串的地址
    INT 0x80的    ;出口
    MOV RAX,1
    MOV RBX,0
    INT 0x80的strlen的:
    MOV RAX,0
    MOV RBX,[RSP + 8]
strlen_loop:
    CMP字节[RBX + RAX] 0
    JE strlen_end
    INC RAX
    JMP strlen_loop
strlen_end:
    RET; LEN在RAX


解决方案

正如我在评论中写道,x​​86_64的用来比系统调用32位Linux的不同方法。特别是 INT 0x80的$ 不再做它的方式(尽管它可能半的工作,如果你已经安装了32位库....)。例如,见这 previous讨论

凡在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;这通常是从32位版本的不同!
MOV RDI,FIRST_PARAM
MOV RSI,SECOND_PARAM
MOV RDX,third_param
系统调用

要打印的程序名,改变你的程序如下,它应该工作。对于任何人在节目中环境看起来如何在启动时的兴致,请参阅here.

  .text段
    全球_start_开始:
    RAX MOV [RSP + 8]
    推RAX
    调用strlen
    加RSP,8    MOV RDI,1; FD =标准输出
    RSI MOV [RSP + 8]; BUF =地址字符串
    MOV RDX,RAX;数= strlen的(字符串)
    MOV RAX,1;写
    系统调用    MOV RDI,0;状态= 0
    MOV RAX,60;出口
    系统调用strlen的:
    MOV RAX,0
    MOV RBX,[RSP + 8]
strlen_loop:
    CMP字节[RBX + RAX] 0
    JE strlen_end
    INC RAX
    JMP strlen_loop
strlen_end:
    RET; LEN在RAX

使用编译:

  NASM -g -f ELF64 -o sc.o sc.asm
GCC -nostartfiles -o SC sc.o

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

解决方案

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

这篇关于学习汇编 - 回声程序名称的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆