在一个简单的32位内核中混合C和汇编代码

在一个简单的32位内核中混合C和汇编代码,c,assembly,x86,kernel,osdev,C,Assembly,X86,Kernel,Osdev,我有一个用C编写的32位内核的简单实现(这是一个独立的实现):(VGA屏幕处于80*25色文本模式) 在这里,getcursor函数似乎工作正常(它获取的光标值范围为0到80*25) 我知道setcursor的实现也是正确的。(我在纯汇编代码中使用过它)。我认为在堆栈上传递值时存在错误。 哪里可能是我错了?看起来错误所在的位置是函数参数传递。 c代码的objdump在调用函数的地方显示: 73: ff 75 f0 pushl -0x10(%ebp) 7

我有一个用C编写的32位内核的简单实现(这是一个独立的实现):(VGA屏幕处于80*25色文本模式)

在这里,getcursor函数似乎工作正常(它获取的光标值范围为0到80*25) 我知道setcursor的实现也是正确的。(我在纯汇编代码中使用过它)。我认为在堆栈上传递值时存在错误。
哪里可能是我错了?

看起来错误所在的位置是函数参数传递。 c代码的objdump在调用函数的地方显示:

  73:   ff 75 f0                pushl  -0x10(%ebp)
  76:   e8 fc ff ff ff          call   77 <printf+0x5e>
  7b:   83 c4 10                add    $0x10,%esp
73:ff 75 f0 PUSH-0x10(%ebp)
76:e8 fc ff呼叫77
7b:83 c4 10添加$0x10,%esp
[ebp-0x10]是我的指针 变量 我感到困惑的地方可能是添加esp,0x10。尽管我只传递了1个参数(4个字节),但它似乎在堆栈上保留了16个字节

但是,看起来[esp]是返回地址(4字节=32位),[esp+4]是第一个参数。。。。也许16个字节是为了正确对齐

感谢迈克尔·佩奇:
彼得·科尔德斯:感谢他们的评论

mov ebx、[esp+0x18]
将不正确。在这种情况下,32位ABI参数在堆栈上传递。ESP+0处是返回地址(通过
调用
指令或等效指令输入)。ESP+4将是第一个参数。如果您使用
mov ebx,[esp+4]
?+4,会发生什么情况?因为IP是32位的。此外,在GCC
-m32
使用的呼叫约定中,ebx保留了呼叫。使用
movzx-ecx,word[esp+4]
将返回地址上方的2个字节加载到ecx中,而不是EBX中。(或使用
gcc-m32-mregparm=3
使其传递EAX、ECX、EDX寄存器中的参数(按该顺序IIRC),而不是低效的堆栈参数约定。)ESP+4,因为返回地址为32位(4字节)(返回地址是ESP+0、ESP+1、ESP+2、ESP+3也是:
xor eax、eax
mov ax、bx
?您是否忘记了
movzx eax、bx
?或者更好的是,以其他顺序读取输入(如果可能的话),以便您在最后的AL中有正确的值,并且可以将另一个值移动到AH中。(并在函数的开头加上xor zero EAX,使其保持零扩展)。
[bits 32]
[global set_cursor]
[global get_cursor]

set_cursor:   ;ebx is the location

        mov ebx,[esp+0x18]
        mov al, 0x0f ;Refer to the index register table port mapping for CRT (low byte)
        mov dx, 0x3d4 ; port number CRT index
        out dx,al   ;Write 0x0f in port 0x3D4  --- note that the port registers are 1 byte in size
        mov dx,0x3d5 ;port number CRT data
        mov al,bl
        out dx,al

        mov al, 0x0e ;Refer to the index register table port mapping for CRT (high byte)
        mov dx, 0x3d4 ; port number CRT index
        out dx,al
        mov dx,0x3d5 ;port number CRT data
        mov al,bh
        out dx,al

        ret

get_cursor:
        mov al, 0x0f ;Refer to the index register table port mapping for CRT (low byte)
        mov dx, 0x3d4 ; port number CRT index
        out dx,al   ;Write 0x0f in port 0x3D4  --- note that the port registers are 1 byte in size
        mov dx,0x3d5 ;port number CRT data
        in al,dx   ;Store the low byte in al -- Hardware forced to use al
        mov bl,al

        mov al, 0x0e ;Refer to the index register table port mapping for CRT (high byte)
        mov dx, 0x3d4 ; port number CRT index
        out dx,al   ;Write 0x0f in port 0x3D4  --- note that the port registers are 1 byte in size
        mov dx,0x3d5 ;port number CRT data
        in al,dx   ;Store the high byte in al -- Hardware forced to use al
        mov bh,al   ;Store the high byte in bh

        xor eax,eax
        mov ax,bx

        ret
  73:   ff 75 f0                pushl  -0x10(%ebp)
  76:   e8 fc ff ff ff          call   77 <printf+0x5e>
  7b:   83 c4 10                add    $0x10,%esp