cbo*_*bot 2 assembly gnu-assembler att intel-syntax x86-16
我正在尝试将 xv6 引导代码从 At&t 语法转换为 Intel 语法,但我在使用 ljmp 指令时遇到了问题。我正在尝试学习 Intel 计算机的启动过程,并且我对 Intel 程序集不是特别擅长。
原始的 AT&T 语法是ljmp $0x8, $start32
.
最小的例子:
.code16
jmp 0x8:start32 # won't assemble
.code32
start32:
nop
Run Code Online (Sandbox Code Playgroud)
使用as -32 -msyntax=intel -mnaked-reg foo.s
和GNU Binutils的2.35.1产生
Error: junk ':start32' after expression
的远JMP线。
我使用 GNU as 和 gcc 工具。
程序集也可能存在其他问题,例如 gdtdesc 和 gdt。
移植到英特尔语法的完整代码是:
# Start the first CPU: switch to 32-bit protectied mode, jump into C.
# The BIOS loads this code from the first sector of the hard disk into
# memory at physical address 0x7c00 and starts executing in real mode
# with cs = 0 and ip = 7c00.
.code16
.global start
start:
# Disable interrupts.
cli
# Zero data segment registers DS, ES, and SS.
xor ax, ax
mov ds, ax
mov es, ax
mov ss, ax
seta20.1:
# Wait for not busy.
in al, 0x64
test al, 0x2
jnz seta20.1
# 0xd1 -> port 0x64
mov al, 0xd1
out 0x64, al
seta20.2:
# Wait for not busy.
in al, 0x64
test al, 0x2
jnz seta20.2
# 0xdf -> port 0x60
mov al, 0xdf
out 0x60, al
# Switch from real to protected mode. Use a bootstrap GDT that makes
# virtual addresses map directly to physical addressses so that the
# effective memory map doesn't change during the transition.
lgdt gdtdesc
# Protection Enable in cr0 register.
mov eax, cr0
or eax, 0x1
mov cr0, eax
# Complete the transtion to 32-bit protected mode by using a long jmp
# to reload cs and eip. The segment descriptors are set up with no
# translation, so that the mapping is still the identity mapping.
# This instruction giving me problems.
ljmp start32, 0x8
.code32
start32:
# Set up the protected-mode data segment registers
mov ax, 0x10
mov ds, ax
mov es, ax
mov ss, ax
# Zero the segments not ready for use.
xor ax, ax
mov fs, ax
mov gs, ax
# Set up the stack pointer and call into C.
mov esp, start
call bootmain
# If bootmain returns spin.. ??
spin:
hlt
jmp spin
# Bootstrap GDT set up null segment, code segment, and data segment respectively.
# Force 4 byte alignment.
.p2align 2
gdt:
.word 0x0000, 0x0000
.byte 0, 0, 0, 0
.word 0xffff, 0x0000
.byte 0, 0x9a, 0xcf, 0
.word 0xffff, 0x0000
.byte 0, 0x92, 0xcf, 0
# sizeof(gdt) - 1 and address of gdt respectively.
gdtdesc:
.word (gdtdesc - gdt - 1)
.long gdt
Run Code Online (Sandbox Code Playgroud)
在您提供的完整翻译代码中,这一行不正确:
ljmp start32, 0x8
Run Code Online (Sandbox Code Playgroud)
GNU Assembler 的 Intel 语法中 FAR JMP 的正确语法是:
ljmp 0x08, start32
Run Code Online (Sandbox Code Playgroud)
选择器值将是第一个,偏移量第二个。似乎在从 AT&T 语法翻译时,当顺序应该保持不变时,您颠倒了这两个值。如果值颠倒,您就会得到错误Error: can't handle non absolute segment in 'ljmp'
。在 GNU Assembler 的 Intel 语法中,您也可以替换ljmp
为jmp
sojmp 0x08, start32
也可以。
Intel 语法有多种风格。jmp 0x8:start32
是 NASM 的 Intel 语法,它不同于 GNU Assembler 的 Intel 语法,其中:
和,
不同。如果您使用 a:
来分隔这两个值,您将Error: junk ':start32' after expression
在 GNU 汇编器中得到错误。
bootmain
不起作用,则可能是与您在此问题中提供的引导加载程序代码无关的问题。如果您还使用 Intel 语法而不是 AT&T 语法构建所有C代码,请确保所有内联程序集都已正确转换为源代码和操作数也将被反转。XV6可能有内联汇编了一些文件,其中包括xv6-public/x86.h
,xv6-public/spinlock.c
,xv6-public/usertests.c
和xv6-public/stressfs.c