흥미로운 문제가 있습니다. 64 비트 시스템 & OS를 사용하고 32 비트 어셈블리 코드를 작성하는 것을 잊어 버렸습니다. 64 비트 코드를 작성하는 방법을 모르겠습니다.64 비트 Linux 및 64 비트 프로세서에서 32 비트 어셈블리 코드 실행하기 : 이상 현상을 설명하십시오.
Linux의 Gnu 어셈블러 (AT & T 구문) 용 x86 32 비트 어셈블리 코드입니다.
이제//hello.S
#include <asm/unistd.h>
#include <syscall.h>
#define STDOUT 1
.data
hellostr:
.ascii "hello wolrd\n";
helloend:
.text
.globl _start
_start:
movl $(SYS_write) , %eax //ssize_t write(int fd, const void *buf, size_t count);
movl $(STDOUT) , %ebx
movl $hellostr , %ecx
movl $(helloend-hellostr) , %edx
int $0x80
movl $(SYS_exit), %eax //void _exit(int status);
xorl %ebx, %ebx
int $0x80
ret
,이 코드는 & 32 비트 OS 바로 32 비트 프로세서에서 잘 실행해야합니까? 64 비트 프로세서는 32 비트 프로세서와 역 호환됩니다. 그래서, 그것은 또한 문제가되지 않을 것입니다. 이 문제는 64 비트 OS & 32 비트 OS에서 시스템 호출 호출 메커니즘의 차이로 인해 발생합니다. 왜 그런지 모르지만 그들은 32 비트 리눅스 & 64 비트 리눅스 사이의 시스템 호출 번호를 변경했습니다.
ASM은/unistd_32.h 정의
#define __NR_write 4
#define __NR_exit 1
ASM/unistd_64.h는 정의
#define __NR_write 1
#define __NR_exit 60
어쨌든 대신 직접 숫자의 매크로를 사용하여 돈을 지불한다. 올바른 시스템 호출 번호를 보장합니다.
내가 조립하면 & 링크 & 프로그램을 실행합니다.
$cpp hello.S hello.s //pre-processor
$as hello.s -o hello.o //assemble
$ld hello.o // linker : converting relocatable to executable
인쇄되지 않음 helloworld
.
은 GDB에서의 전시는 :
- 프로그램은 내가 GDB로 디버깅하는 방법을 모르는 코드 01
로 종료. 튜토리얼을 사용하여 디버깅을 시도하고 각 단계에서 레지스터 검사 명령으로 명령을 실행했습니다. 항상 "나와 함께 프로그램을 종료 01". 몇 가지 방법으로이 문제를 디버깅하는 방법을 보여 주면 좋을 것입니다.
(gdb) break _start
Note: breakpoint -10 also set at pc 0x4000b0.
Breakpoint 8 at 0x4000b0
(gdb) start
Function "main" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Temporary breakpoint 9 (main) pending.
Starting program: /home/claws/helloworld
Program exited with code 01.
(gdb) info breakpoints
Num Type Disp Enb Address What
8 breakpoint keep y 0x00000000004000b0 <_start>
9 breakpoint del y <PENDING> main
나는 strace
을 실행 해 보았습니다.
execve("./helloworld", ["./helloworld"], [/* 39 vars */]) = 0
write(0, NULL, 12 <unfinished ... exit status 1>
- 이 strace를의 출력에
write(0, NULL, 12)
시스템 호출의 매개 변수 설명 :이 출력입니까? - 무엇 정확히이보고 있나요? 정확히이 exitstatus = 1로 종료되는 이유를 알고 싶습니다.
- gdb를 사용하여이 프로그램을 디버깅하는 방법을 보여줄 수 있습니까?
- 시스템 호출 번호가 변경된 이유는 무엇입니까?
- 이 컴퓨터에서이 프로그램을 올바르게 실행할 수 있도록이 프로그램을 적절하게 변경하십시오.
편집 :
폴 R의 답변을 읽은 후. 나는 내 파일 I이 32 비트 재배치 & 실행 ELF해야한다는 그에게 동의
[email protected]:~$ file ./hello.o
./hello.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
[email protected]:~$ file ./hello
./hello: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped
를 확인했습니다. 그러나 그것은 나의 제 질문에 답하지 않습니다. 내 모든 질문은 여전히 질문입니다. 이 사건에서 정확히 무슨 일이 일어 났습니까? 누군가 내 질문에 답하고이 코드의 x86-64 버전을 제공 할 수 있습니까?
'_start' 또는'main'의 차이점은 무엇입니까? – claws
@claws : 코드를 gcc와 쉽게 만들고 링크 할 수 있도록 변경 한 것뿐입니다.하지만 main이 호출되기 전에 C 런타임 라이브러리 시작 코드가 실행된다는 것을 의미하는 것으로 생각됩니다. –
내 질문을 편집했습니다. 또한'gcc -Wall test '를 사용하여 코드를 빌드하려고 할 때.S -m32 -o test'이 오류가 발생합니다 (밑줄은 분리 기호로 사용됩니다) : /usr/bin/ld : 호환되지 않는 /usr/lib/gcc/x86_64-linux-gnu/4.4.1/libgcc.a를 건너 뜁니다. -lgcc를 검색 할 때 을 검색 할 때 ______________ /usr/bin/ld : 호환되지 않는 /usr/lib/gcc/x86_64-linux-gnu/4.4.1/libgcc.a를 건너 뛰는 경우 ______________ /usr/bin/ld : ld : -lgcc를 찾을 수 없습니다. ______________ collect2 : ld가 1을 반환했습니다. 종료 상태 – claws