来自 AT&T 语法的 Intel Assembly ljmp 语法 [英] Intel Assembly ljmp syntax from AT&T syntax

查看:112
本文介绍了来自 AT&T 语法的 Intel Assembly ljmp 语法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to convert the xv6 boot code from At&t syntax to Intel syntax and I have a problem with the ljmp instruction. I am trying to learn the boot process of Intel computers and I am not particularly strong with Intel assembly.

最初的 AT&T 语法是 ljmp $0x8, $start32.

The original AT&T syntax is 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 产生
错误:表达式后的垃圾 ':start32' 对于远 jmp 行.

Using as -32 -msyntax=intel -mnaked-reg foo.s with GNU Binutils 2.35.1 produces
Error: junk ':start32' after expression for the far jmp line.

我使用 GNU as 和 gcc 工具.
程序集也可能存在其他问题,例如 gdtdesc 和 gdt.

I am using GNU as, and gcc tools.
There might also be other problems with the assembly such as the gdtdesc and gdt.

移植到英特尔语法的完整代码是:

The full code ported to Intel syntax is:

# 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

推荐答案

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

In the complete translated code you presented, this line is incorrect:

ljmp start32, 0x8

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

The proper syntax for a FAR JMP in GNU Assembler's Intel syntax is:

ljmp 0x08, start32

选择器值将是第一个,偏移量第二个.似乎在从 AT&T 语法翻译时,当顺序应该保持不变时,您颠倒了这 2 个值.将值反转后,您将收到错误 Error: can't handle non absolute segment in 'ljmp'.在 GNU Assembler 的 Intel 语法中,您还可以将 ljmp 替换为 jmp,这样 jmp 0x08, start32 也能正常工作.

The selector value would be first and the offset second. It seems in translating from AT&T syntax you reversed these 2 values when the order should have remained the same. With the values reversed you would have got the error Error: can't handle non absolute segment in 'ljmp'. In GNU Assembler's Intel syntax you can also substitute ljmp with jmp so jmp 0x08, start32 would work as well.

英特尔语法有多种风格.jmp 0x8:start32 是 NASM 的 Intel 语法,它不同于 GNU Assembler 的 Intel 语法,其中 :, 不同.如果您使用 : 分隔这两个值,您将在 GNU 汇编程序中得到错误 Error:junk ':start32' after expression.

There are different flavors of Intel syntax. jmp 0x8:start32 is NASM's Intel syntax and it differs from GNU Assembler's Intel syntax where the : and , differ. If you used a : to separate the two values you would get the error Error: junk ':start32' after expression in GNU Assembler.

  • 如果 bootmain 中的代码不起作用,则可能是与您在此问题中提供的引导加载程序代码无关的问题.如果您还使用英特尔语法而不是 AT&T 语法构建所有 C 代码,请确保所有内联程序集都已正确转换为源代码和操作数也将被反转.xv6 可能在许多文件中包含内联汇编,包括 xv6-public/x86.hxv6-public/spinlock.cxv6-public/usertests.cxv6-public/stressfs.c
  • If the code in bootmain doesn't work it is likely an issue unrelated to the bootloader code you presented in this question. If you are also building all the C code with Intel Syntax rather than AT&T syntax, then make sure all the inline assembly has been properly converted as source and operand would have been reversed as well. xv6 likely has inline assembly in a number of files including xv6-public/x86.h, xv6-public/spinlock.c, xv6-public/usertests.c and xv6-public/stressfs.c

这篇关于来自 AT&T 语法的 Intel Assembly ljmp 语法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆