程序集:用于自定义 OS 键盘支持的引导加载程序
Assembly: boot loader for custom OS keyboard support
我有一个工作简单的自定义 OS(现在没有做太多 :D)。现在我正在使用不支持键盘的程序集文件 (boot.s)。
程序集文件(boot.s):
# set magic number to 0x1BADB002 to identified by bootloader
.set MAGIC, 0x1BADB002
# set flags to 0
.set FLAGS, 0
# set the checksum
.set CHECKSUM, -(MAGIC + FLAGS)
# set multiboot enabled
.section .multiboot
# define type to long for each data defined as above
.long MAGIC
.long FLAGS
.long CHECKSUM
# set the stack bottom
stackBottom:
# define the maximum size of stack to 512 bytes
.skip 512
# set the stack top which grows from higher to lower
stackTop:
.section .text
.global _start
.type _start, @function
_start:
# assign current stack pointer location to stackTop
mov $stackTop, %esp
# call the kernel main source
call KERNEL_MAIN
cli
# put system in infinite loop
hltLoop:
hlt
jmp hltLoop
.size _start, . - _start
我认为这是缺失的部分,但它是 intel 语法,我无法使用它。
load_idt:
mov edx, [esp + 4]
lidt [edx]
sti
ret
read_port:
mov edx, [esp + 4]
in al, dx
ret
write_port:
mov edx, [esp + 4]
mov al, [esp + 4 + 4]
out dx, al
ret
keyboard_handler:
call keyboard_handler
iretd
我正在使用以下命令编译 boot.s:
as --32 boot.s -o boot.o
谁能帮我把键盘部分(Intel 语法)翻译成 AT&T? :)
有关如何将 NASM Intel 语法转换为 GAS 的 AT&T 语法的信息,请参见此 Whosebug Answer, and a lot of useful information is provided in this IBM article。您的代码具体如下所示:
load_idt:
mov 4(%esp), %edx
lidt (%edx)
sti
ret
read_port:
mov 4(%esp), %edx
in %dx, %al
ret
write_port:
mov 4(%esp), %edx
mov 8(%esp), %al
out %al, %dx
ret
keyboard_handler:
call keyboard_handler
iret
总的来说,最大的区别是:
- 使用 AT&T 语法,源在左边,目标在右边,Intel 则相反。
- 使用 AT&T 语法,寄存器名称前加
%
- 使用 AT&T 语法,立即值会在前面加上
$
- 内存操作数可能是最大的区别。 NASM 使用 [segment:disp+base+index*scale] 而不是 GAS 的语法 segment:disp(base, index, scale).
其他观察结果
我建议将堆栈从多重启动部分移到 .bss
部分。 BSS 部分通常不会占用输出可执行文件中的 space(假设使用正常或默认的链接描述文件)。可以在 .text
部分之后以这种方式定义堆栈:
.section .bss
.lcomm stackBottom 512
stackTop:
我有一个工作简单的自定义 OS(现在没有做太多 :D)。现在我正在使用不支持键盘的程序集文件 (boot.s)。
程序集文件(boot.s):
# set magic number to 0x1BADB002 to identified by bootloader
.set MAGIC, 0x1BADB002
# set flags to 0
.set FLAGS, 0
# set the checksum
.set CHECKSUM, -(MAGIC + FLAGS)
# set multiboot enabled
.section .multiboot
# define type to long for each data defined as above
.long MAGIC
.long FLAGS
.long CHECKSUM
# set the stack bottom
stackBottom:
# define the maximum size of stack to 512 bytes
.skip 512
# set the stack top which grows from higher to lower
stackTop:
.section .text
.global _start
.type _start, @function
_start:
# assign current stack pointer location to stackTop
mov $stackTop, %esp
# call the kernel main source
call KERNEL_MAIN
cli
# put system in infinite loop
hltLoop:
hlt
jmp hltLoop
.size _start, . - _start
我认为这是缺失的部分,但它是 intel 语法,我无法使用它。
load_idt:
mov edx, [esp + 4]
lidt [edx]
sti
ret
read_port:
mov edx, [esp + 4]
in al, dx
ret
write_port:
mov edx, [esp + 4]
mov al, [esp + 4 + 4]
out dx, al
ret
keyboard_handler:
call keyboard_handler
iretd
我正在使用以下命令编译 boot.s:
as --32 boot.s -o boot.o
谁能帮我把键盘部分(Intel 语法)翻译成 AT&T? :)
有关如何将 NASM Intel 语法转换为 GAS 的 AT&T 语法的信息,请参见此 Whosebug Answer, and a lot of useful information is provided in this IBM article。您的代码具体如下所示:
load_idt:
mov 4(%esp), %edx
lidt (%edx)
sti
ret
read_port:
mov 4(%esp), %edx
in %dx, %al
ret
write_port:
mov 4(%esp), %edx
mov 8(%esp), %al
out %al, %dx
ret
keyboard_handler:
call keyboard_handler
iret
总的来说,最大的区别是:
- 使用 AT&T 语法,源在左边,目标在右边,Intel 则相反。
- 使用 AT&T 语法,寄存器名称前加
%
- 使用 AT&T 语法,立即值会在前面加上
$
- 内存操作数可能是最大的区别。 NASM 使用 [segment:disp+base+index*scale] 而不是 GAS 的语法 segment:disp(base, index, scale).
其他观察结果
我建议将堆栈从多重启动部分移到 .bss
部分。 BSS 部分通常不会占用输出可执行文件中的 space(假设使用正常或默认的链接描述文件)。可以在 .text
部分之后以这种方式定义堆栈:
.section .bss
.lcomm stackBottom 512
stackTop: