来自AT&T语法的IntelAssemblyljmp语法

我正在尝试将 xv6 引导代码从 At&t 语法转换为 Intel 语法,但我在使用 ljmp 指令时遇到了问题。我正在尝试学习 Intel 计算机的启动过程,并且我对 Intel 程序集不是特别擅长。

原始的 AT&T 语法是ljmp $0x8, $start32.

最小的例子:

.code16
   jmp 0x8:start32          # won't assemble

.code32
start32:
   nop

使用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

回答

在您提供的完整翻译代码中,这一行不正确:

ljmp start32, 0x8

GNU Assembler 的 Intel 语法中 FAR JMP 的正确语法是:

ljmp 0x08, start32

选择器值将是第一个,偏移量第二个。似乎在从 AT&T 语法翻译时,当顺序应该保持不变时,您颠倒了这两个值。如果值颠倒,您就会得到错误Error: can't handle non absolute segment in 'ljmp'。在 GNU Assembler 的 Intel 语法中,您也可以替换ljmpjmpsojmp 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.hxv6-public/spinlock.cxv6-public/usertests.cxv6-public/stressfs.c
  • Added the xv6 code to github: https://github.com/christianchabot/xv6-small

以上是来自AT&T语法的IntelAssemblyljmp语法的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>