NASM 链接到 C 偏移量
NASM linked with C offset
我正在为 C 构建一个简单的执行环境,通过引导加载程序引导。引导可执行文件运行良好,但我无法从 C 调用 asm 例程。我在 ASM 中定义了一个函数 'putchar',它应该可以从 C 调用。问题是在调试期间从它的外观来看所有调用nasm 编译的程序集似乎少了几个字节。
C源代码如下:
#include "io.h"
void kmain() {
putchr('!', 5);
while(1);
}
与io.h
:
extern void putchr(char c, int repeat);
编译成:
│0x600 <kmain> push
│0x601 <kmain+1> mov bp,sp
│0x603 <kmain+3> sub sp,0x18
│0x606 <kmain+6> mov WORD PTR [si+0x24],0x504
│0x60b <kmain+11> add BYTE PTR [bx+si],al
│0x60d <kmain+13> add bh,al
│0x60f <kmain+15> add al,0x24
│0x611 <kmain+17> and WORD PTR [bx+si],ax
│0x613 <kmain+19> add BYTE PTR [bx+si],al
│0x615 <kmain+21> call 0x625 ; Should be call to putchr
│0x618 <kmain+24> add BYTE PTR [bx+si],al
│0x61a <kmain+26> jmp 0x61a <kmain+26> ; I suppose this is while(1)
putchr 在程序集中定义并在那里调用另一个内部函数:
bits 32
global putchr
nop
nop
nop
xor eax, eax
nop
nop
putchr:
; PutChar expects: al = character (first arg), cx = repeat (second arg)
push ebp
mov ebp, esp
mov eax, [ebp + 8] ; First arg
and eax, 0xFF ; Only interested in lower 8 bytes (8-bit al register)
; Note at this point eax = 0xc3/195 and not 0x21/33 as I'd expect
mov cx, [ebp + 12] ; Second arg
call PutChar
对 putchr 的调用是错误的,因为 putchr 不在 0x625
但我的程序集文件顶部的倒数第二个 nop
在那里。 putchr
从 0x627
开始。我想这也是我无法从 C.
读取传递的值('!' 和 5)的原因
我正在编译和链接如下:
nasm -f elf32 -F dwarf -g io.asm -o ../build/os/imm/asm/io.o
gcc -ffreestanding -nostdlib -gdwarf-4 -m32 -ggdb3 -c kernel.c -o ../build/os/imm/c/kernel.o
ld -m elf_i386 -nmagic -Tos.lds ../build/os/imm/c/kernel.o ../build/os/imm/asm/io.o -o ../build/os/os
链接描述文件 os.lds
相当基础和直接:
ENTRY(kmain);
PHDRS {
headers PT_PHDR FILEHDR PHDRS;
code PT_LOAD;
}
SECTIONS {
.text 0x600: ALIGN(0x100) { *(.text) } :code
.data : { *(data) }
.bss : { *(bss) }
/DISCARD/ : { *(.eh_frame) }
}
为什么会有这么奇怪的 0x2 偏移量,为什么不能从程序集实现中获取函数参数?
不幸的是,我从来没有发现这个问题,但我使用的是 16 位 C,因为我想在摆弄一段时间后让 something 工作。切换回 32 位我终于找到了问题:
mov esp, [stack]
我没有将 esp
设置为堆栈的地址,而是将其设置为堆栈的 value。 OSDev wiki 指出 OS 开发可能会导致调试数小时,然后才能在您面前看到答案!
我正在为 C 构建一个简单的执行环境,通过引导加载程序引导。引导可执行文件运行良好,但我无法从 C 调用 asm 例程。我在 ASM 中定义了一个函数 'putchar',它应该可以从 C 调用。问题是在调试期间从它的外观来看所有调用nasm 编译的程序集似乎少了几个字节。
C源代码如下:
#include "io.h"
void kmain() {
putchr('!', 5);
while(1);
}
与io.h
:
extern void putchr(char c, int repeat);
编译成:
│0x600 <kmain> push
│0x601 <kmain+1> mov bp,sp
│0x603 <kmain+3> sub sp,0x18
│0x606 <kmain+6> mov WORD PTR [si+0x24],0x504
│0x60b <kmain+11> add BYTE PTR [bx+si],al
│0x60d <kmain+13> add bh,al
│0x60f <kmain+15> add al,0x24
│0x611 <kmain+17> and WORD PTR [bx+si],ax
│0x613 <kmain+19> add BYTE PTR [bx+si],al
│0x615 <kmain+21> call 0x625 ; Should be call to putchr
│0x618 <kmain+24> add BYTE PTR [bx+si],al
│0x61a <kmain+26> jmp 0x61a <kmain+26> ; I suppose this is while(1)
putchr 在程序集中定义并在那里调用另一个内部函数:
bits 32
global putchr
nop
nop
nop
xor eax, eax
nop
nop
putchr:
; PutChar expects: al = character (first arg), cx = repeat (second arg)
push ebp
mov ebp, esp
mov eax, [ebp + 8] ; First arg
and eax, 0xFF ; Only interested in lower 8 bytes (8-bit al register)
; Note at this point eax = 0xc3/195 and not 0x21/33 as I'd expect
mov cx, [ebp + 12] ; Second arg
call PutChar
对 putchr 的调用是错误的,因为 putchr 不在 0x625
但我的程序集文件顶部的倒数第二个 nop
在那里。 putchr
从 0x627
开始。我想这也是我无法从 C.
我正在编译和链接如下:
nasm -f elf32 -F dwarf -g io.asm -o ../build/os/imm/asm/io.o
gcc -ffreestanding -nostdlib -gdwarf-4 -m32 -ggdb3 -c kernel.c -o ../build/os/imm/c/kernel.o
ld -m elf_i386 -nmagic -Tos.lds ../build/os/imm/c/kernel.o ../build/os/imm/asm/io.o -o ../build/os/os
链接描述文件 os.lds
相当基础和直接:
ENTRY(kmain);
PHDRS {
headers PT_PHDR FILEHDR PHDRS;
code PT_LOAD;
}
SECTIONS {
.text 0x600: ALIGN(0x100) { *(.text) } :code
.data : { *(data) }
.bss : { *(bss) }
/DISCARD/ : { *(.eh_frame) }
}
为什么会有这么奇怪的 0x2 偏移量,为什么不能从程序集实现中获取函数参数?
不幸的是,我从来没有发现这个问题,但我使用的是 16 位 C,因为我想在摆弄一段时间后让 something 工作。切换回 32 位我终于找到了问题:
mov esp, [stack]
我没有将 esp
设置为堆栈的地址,而是将其设置为堆栈的 value。 OSDev wiki 指出 OS 开发可能会导致调试数小时,然后才能在您面前看到答案!