【问题标题】:NASM linked with C offsetNASM 与 C 偏移链接
【发布时间】:2017-02-19 16:40:50
【问题描述】:

我正在为 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 在那里。 putchr0x627 开始。我想这也是我无法读取从 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 位和 32 位代码。您是如何设法将kmain 编译为 16 位的并不明显?
  • 根据命令行参数(-m32),除了汇编文件中的bits 32外,所有内容都编译为32位。
  • 其实我认为你的kmain是32位的,你只是把它错误地反汇编为16位。现在的问题当然是,你在什么模式下运行它?如果你没有切换到 32 位保护模式,cpu 将执行代码为 16 位,这将无法正常工作。
  • 你是对的。 kmain 编译为 32 位。但是,如果我使用-m16 编译,退出例程时会发生 CPU 崩溃。

标签: c assembly nasm calling-convention


【解决方案1】:

不幸的是,我从未发现过这个问题,但我使用的是 16 位 C,因为我想让 something 在摆弄一段时间后工作。切换回32位终于找到问题了:

mov esp, [stack]

我没有将esp 设置为堆栈的地址,而是将其设置为堆栈的。 OSDev wiki 指出 OSDev wiki 指出 OS 开发可能会导致数小时的调试在您面前看到答案之前并没有错!

【讨论】:

    猜你喜欢
    • 2014-09-19
    • 2011-01-29
    • 2017-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-27
    相关资源
    最近更新 更多