對於某些背景,我對彙編器很陌生,我的彙編器是NASM。對於我的第一個項目,我在Windows 8.1上使用了cygwin,並且試圖將來自第二個答案的信息從32位轉換爲64位:How to write hello world in assembler under Windows?我似乎無法從WinAPI NASM教程中解決這個LD錯誤
我正在使用gnu ld的鏈接。因爲我的系統上的kernel32.Lib似乎搞砸了,而且我更喜歡gnu ld。所以,這是我的彙編:
global _main
extern [email protected]
extern [email protected]
extern [email protected]
section .text
_main
push rbp
mov rbp, rsp
sub rsp, 4
; hStdOut = GetStdHandle(STD_OUTPUT_HANDLE)
push -11
call [email protected]
mov rbx, rax
; WriteFile(hStdOut, message, length(message), &bytes, 0)
push 0
lea rax, [rbp-4]
push rax
push (message_end - message)
push message
push rbx
call [email protected]
mov rsp, rbp
pop rbp
; ExitProcess(0)
push 0
call [email protected]
;
hlt
message db 'Hello, World!', 10
message_end
當我運行nasm -fwin64 ./test.asm
它沒有錯誤,只有我的警告留出的標籤名稱的冒號組裝。
我使用鏈接到WinAPI的命令是
ld test.obj -lkernel32 --enable-stdcall-fixup /cygdrive/c/Windows/system32/kernel32.dll -o test.exe
這給我留下了
test.obj:./test.asm:(.text+0x1c): relocation truncated to fit: R_X86_64_32 against `.text'
所以,我用谷歌對我有利,發現這個計算器的問題: What does this GCC error "... relocation truncated to fit..." mean?
我在第一個答案中閱讀材料,並搜索了一些谷歌,然後嘗試第二個答案中提供的解決方案。這裏是我的鏈接腳本
SECTIONS
{
. = 0x000000000000001b;
.text :
{
*(*)
}
}
我嘗試使用此命令鏈接:
ld test.obj -T test.ld -lkernel32 --enable-stdcall-fixup /cygdrive/c/Windows/system32/kernel32.dll -o test.exe
而且我得到這個錯誤:在這裏我放置-T test.ld
ld: cannot find -lkernel32
不管我得到這個錯誤選項。
我被卡住了,我的google-foo似乎還不足以找到幫助。我不明白爲什麼LD在指定鏈接器腳本時找不到kernel32,而且我也不知道如何解決截斷問題。
如果有幫助,與拆遷數據objdump的爲test.obj
是:
$ objdump -Sr test.obj
test.obj: file format pe-x86-64
Disassembly of section .text:
0000000000000000 <_main>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: 48 83 ec 04 sub $0x4,%rsp
8: 6a f5 pushq $0xfffffffffffffff5
a: e8 00 00 00 00 callq f <_main+0xf>
b: R_X86_64_PC32 [email protected]
f: 48 89 c3 mov %rax,%rbx
12: 6a 00 pushq $0x0
14: 48 8d 45 fc lea -0x4(%rbp),%rax
18: 50 push %rax
19: 6a 0e pushq $0xe
1b: 68 32 00 00 00 pushq $0x32
1c: R_X86_64_32 .text
20: 53 push %rbx
21: e8 00 00 00 00 callq 26 <_main+0x26>
22: R_X86_64_PC32 [email protected]
26: 48 89 ec mov %rbp,%rsp
29: 5d pop %rbp
2a: 6a 00 pushq $0x0
2c: e8 00 00 00 00 callq 31 <_main+0x31>
2d: R_X86_64_PC32 [email protected]
31: f4 hlt
0000000000000032 <message>:
32: 48 rex.W
33: 65 6c gs insb (%dx),%es:(%rdi)
35: 6c insb (%dx),%es:(%rdi)
36: 6f outsl %ds:(%rsi),(%dx)
37: 2c 20 sub $0x20,%al
39: 57 push %rdi
3a: 6f outsl %ds:(%rsi),(%dx)
3b: 72 6c jb a9 <message_end+0x69>
3d: 64 21 0a and %ecx,%fs:(%rdx)
感謝。
爲未來的谷歌猴子__SOLUTION EDIT__:
使用從@Jester答案的信息,我重寫了程序,現在按預期工作。下面是工作源:
global main
extern [email protected]
extern [email protected]
extern [email protected]
section .text
main
push rbp
mov rbp, rsp
sub rsp, 8
; hStdOut = GetStdHandle(STD_OUTPUT_HANDLE)
; ABI, pass in registers
mov rcx, -11
call [email protected]
mov rbx, rax
; WriteFile(hStdOut, message, length(message), &bytes, 0)
mov rcx, rbx
lea rax, [rel message]
mov rdx, rax
mov r8, (message_end - message)
lea rax, [rbp-8]
mov r9, rax
push 0
call [email protected]
mov rsp, rbp
pop rbp
; ExitProcess(0)
mov rcx, 0
call [email protected]
;
hlt
message db 'Hello, World!', 10
message_end
好的,謝謝!二進制文件現在鏈接,但它在WriteFile()調用上生成分段錯誤。這是因爲x64上的調用約定(是ARM ABI嗎?)。在這種情況下,我是否應該按照本頁所述將參數移動到r寄存器中:http://eli.thegreenplace.net/2011/09/06/stack-frame-layout-on-x86-64/ –
I已經將你的官方msdn文檔鏈接到了......並且不,它與ARM無關。 – Jester
好的。我現在明白了,並且已經與工作來源更新了操作。謝謝一堆! –