나는 최근에 x86-64 어셈블리를 사용하기로 결정했습니다. argv를 표시 할 때 문제가 발생했습니다x86-64 linux assembly. EFAULT 때문에 argv에서 쓰기를 사용하면 작동하지 않습니까? "잘못된 주소"
예 제가 작성한 코드는 좋지 않습니다. 가정을 만들고 오류를 확인하지는 않지만 실제로 그 원인이라고 생각하지 않습니다. 이 문제.
여기 내 프로그램이 핵심입니다.
.globl _start
.text
main:
_start:
movl $10,%edx # No. of chars to write
movq 16(%rsp),%rcx # argv[1]
movl $1,%ebx # stdout
movl $4,%eax # write
int $0x80
movl $0,%ebx
movl $1,%eax
int $0x80
나는
을 helloworldddddddddd ./myprog 내 프로그램을 실행 그래서 변수는 argv [0] =./MYPROG 와는 argv [1] = helloworlddddddddddd 아니면
를 입력 어떤 내 프로그램은 첫 번째를 작성해야argv [1]의 10 문자는 stdout에 저장됩니다.
예외 : 작동하지 않는 경우. 쓰기가 -14로 반환됩니다. 오류 EFAULT입니까? 나쁜 주소를 의미합니다.
그래서 나는이 대신 .globl _start
.text
main:
_start:
movq 16(%rsp),%rax
movq $bob,%rbx
subq %rcx,%rcx
.Lloop:
movb (%rax,%rcx),%dl
movb %dl,(%rbx,%rcx)
cmpb $0,%dl
je .Ldone
addq $1,%rcx
jmp .Lloop
.Ldone: movl $10,%edx
movq $bob,%rcx
movl $1,%ebx
movl $4,%eax
int $0x80
movl $0,%ebx
movl $1,%eax
int $0x80
.comm bob,50
그것은 복사 [1] 메모리 영역에 내가 전화 한 밥을 argv를 한 다음 표준 출력이 복사본을 쓰려고 썼다. 나는 심한 x86이라고 확신하지만, 제대로 작동합니다. 나는이 프로그램을 컴파일하고 실행하면 [1]
마지막으로 좀 더 내 초 이상 내 첫 번째 프로그램처럼#include <unistd.h>
int main(int argc, char **argv) {
write(1,argv[1],10);
return 0;
}
C
이 썼다는 argv에 있던 어떤 출력뿐만 아니라 작동합니다. 이 단계까지 나는 완전히 당혹 스럽다.그래서 "쓰기"시스템 호출은 내 프로그램의 argv 배열을 읽을 수 없지만 사본을 읽을 수 있습니다. 아, 그리고 C로 쓰면 작동합니다. 이것은 완전히 기괴한 것 같습니다. 아무도 나에게 무슨 일이 일어나고 있는지, 왜 말해 줄 수 있습니까?
편집 :
그것은 내가 혼합 된 32 비트 및 64 비트 코드를 사용하고 있음을 지적하고있다. 그래서 나는 100 % 64bit로 바꿨다.
첫 번째 프로그램 :
.globl _start
.text
main:
_start:
movl $10,%edx # No. of chars to write
movl 16(%rsp),%esi # argv[1]
movl $1,%edi # stdout
movl $1,%eax # write
syscall
movl $0,%edi
movl $60,%eax
syscall
번째 프로그램 : 심지어 지금 64 비트, 그리고 두 번째 프로그램이 여전히 작동하지만 여전히
.globl _start
.text
main:
_start:
movq 16(%rsp),%rax
movq $bob,%rbx
subq %rcx,%rcx
.Lloop:
movb (%rax,%rcx),%dl
movb %dl,(%rbx,%rcx)
cmpb $0,%dl
je .Ldone
addq $1,%rcx
jmp .Lloop
.Ldone: movl $10,%edx # No. of chars to write
movq $bob,%rsi # buffer
movl $1,%edi # stdout
movl $1,%eax # write
syscall
movl $0,%edi # return 0
movl $60,%eax # exit
syscall
.comm bob,50
같은 오류가 첫 번째 프로그램은 여전히도 작동하지 그것도 지금은 64bit
첫번째 프로그램의 64 비트 버전을위한 Strace. (작동하지 않는 한) :
execve("./Myprog", ["./Myprog", "bananablahblah"], [/* 46 vars */]) = 0
write(1, 0x1491f543, 10) = -1 EFAULT (Bad address)
_exit(0) = ?
+++ exited with 0 +++
나는 gdb가 불평을 멈추기 위해 주에 넣었습니다. 그것은 그것없이 잘 동작합니다. 나는 32 비트 64 비트 int 대 시스템 콜에 대해 몰랐다. 고마워, 내가 살펴 보겠다.하지만 여전히 내 문제의 주요 부분이라고 생각하지 않는다. – user3429500
그가 말하는 것은 당신이받는 오류와 일치한다. "잘못된 주소"라는 오류는 쓰기를 시도한 메모리의 주소가 잘못되어 액세스 할 수 없거나 다른 주소로 액세스 할 수 없음을 의미합니다. 다른 것 같지 않으므로 제거 프로세스에 따라 duskwuff의 'int 80'대답이 문제가됩니다. – Tyler
그렇지 않은 경우. 방금 두 프로그램 모두 64 비트 시스템 호출을 사용하도록 다시 작성했는데 첫 번째 프로그램은 여전히 작동하지 않고 두 번째 프로그램은 여전히 작동합니다. – user3429500