:
여기 내 코드입니다.
64bit Ubuntu
과 pushq %rax
나는 당신이 64 비트 실행 파일을 만들려고한다고 추측합니다.
그 다음, 그렇다면 ... 여기
:
pushq %rax
pushq $output
call printf
addl $8, %esp
가 제대로 함수 호출 후 스택을 균형 아닙니다. 이것이 여전히 64 비트 코드라는 것을 기억하십니까? rsp
에 추가해야합니다 (esp
이 아님). 또한 2 개의 8 바이트 매개 변수를 푸시하는 경우 정확히 2 개의 8 바이트 매개 변수를 제거해야합니다. 즉 8을 추가하지 말고 16을 추가해야합니다.
그러나 그보다 더 나쁩니다. 64 비트 모드에서는 매개 변수가 다르게 전달됩니다. 제 1 파라미터는 레지스터 (rdi
, rsi
, rdx
, rcx
, r8
및 r9
)에있다. 그래서, 우리를 제공합니다 : 여기
movq %rax, %rsi
movq $output, %rdi
movq $0, %rax ; number of vector registers used for var-arg-function printf()
call printf
:
inc %edi
당신은 바로 호출 및 매개 변수 전달이 레지스터를 사용하여 rdi
의 가치를 파괴했다. 전화하기 전에 수동으로 rdi
을 누른 다음 다시 팝업해야합니다. 또는 전역 변수에 저장할 수 있습니다. 밀어 넣기 및 팝하기를 선택하는 경우 스택 포인터 rsp
이 항상 call
명령보다 먼저 16 바이트 정렬되어 있는지 확인하십시오. 여기
:
movl $0, %ebx
movl $1, %eax
int $0x80
32 비트 시스템 호출 인터페이스를 사용하고 있습니다. 64 비트 프로그램에서 당신은 64 비트 시스템 호출 인터페이스를 사용해야합니다 : 이제
movq $60, %rax ; sys_exit
movq $0, rdi ; return 0 (success)
syscall
을, 나는이 일이 너무 문제가있을 수 있습니다 생각 :
일반적으로
movl $0, %edi
loop :
movl values(, %edi, 4), %eax
, 당신은 안 64 비트 코드의 주소 계산에 32 비트 레지스터 및 32 비트 명령어 사용 나는로 변경 것 : 두 작품 중 어느 것도 values
의 주소가 2GB 이하 더 rip
(멀리 있기 때문에 경우
movl $0, %rdi
loop :
movl values(, %rdi, 4), %eax
사실 : 변위는 대부분의 지시에 메모리 피연산자에 부호있는 32 비트 정수로 제한됩니다 64 비트 모드에서는 대다수가 64 비트 모드에서 변위 메모리 연산 코드를 사용하지 않고 rip
- 상대 주소 지정을 사용하는 경우), 수동으로 64 비트 주소 values
과 색인을 수동으로 추가해야합니다. 배열에 4를 곱합니다. 도중에 잘라내기를하지 않고 64 비트 추가를 수행해야합니다.
는해야 하 읽
Agner 안개 다른 C++ 컴파일러에 대한 규칙과 운영 체제를 호출 0.99.6
당신의'e__' 레지스터의 대부분은'r__'이어야한다고 생각합니다. 이것은 x86 어셈블리로 작성되었으며 모든 필요한 변경을하지 않고 강제로 x64로 이식 된 것 같습니다. – Mysticial
나는 그것을 시도했지만 작동하지 않습니다. – Nmzzz
64 비트로 조립 되었습니까? 그럼 스택은 DWORD가 아니라 QWORD가 맞춰 졌기 때문에 rsp에 8을 더하는 것은 잘못되었습니다. printf 호출 후 rsp에 16을 더해야합니다 – Gunner