学习汇编 - 回声程序名称 [英] Learning assembly - echo program name
问题描述
我想写组装一个简单的程序,将写出来的程序的名称。使用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
正如我在评论中写道,x86_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屋!