You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

汇编带偏移长跳转的不同语法及内核GDT编写的汇编链接问题

Understanding Far Jump Syntax for GDT Flush Across Assemblers

Hey there! Sounds like you're making solid progress on your kernel's GDT setup—awesome stuff. Let's dive into the different assembly syntaxes for that critical far jump we need to update the CS register after loading a new GDT.

First, a quick recap: We can't just mov a new value into CS directly. A far jump is required because it's the only way to atomically set both the segment selector (for CS) and the offset, forcing the CPU to recognize the new GDT's code segment.

1. NASM Syntax (likely what your tutorial uses)

NASM uses a straightforward segment:offset syntax for far jumps. Here's how the full gdt_flush routine might look, matching your tutorial's structure:

global _gdt_flush  ; Expose this function to C code
_gdt_flush:
    ; Grab the GDT pointer address passed from C
    mov eax, [esp+4]
    ; Load the new GDT
    lgdt [eax]

    ; Update all data segment registers with the new data selector (0x10 here)
    mov ax, 0x10
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    mov ss, ax

    ; Far jump to update CS: use code segment selector (0x08) and jump to local label
    jmp 0x08:.flush
.flush:
    ; Return back to C code
    ret

The key line here is jmp 0x08:.flush—0x08 is your GDT's code segment selector, and .flush is the offset within that segment.

2. GNU Assembler (GAS) Syntax

GAS uses a reversed syntax compared to NASM, with $ prefixes for immediate values. Far jumps use the ljmp instruction:

.global gdt_flush  ; Make function visible to C
gdt_flush:
    ; Get GDT pointer from stack (C function argument)
    movl 4(%esp), %eax
    lgdt (%eax)

    ; Update data segment registers
    movw $0x10, %ax
    movw %ax, %ds
    movw %ax, %es
    movw %ax, %fs
    movw %ax, %gs
    movw %ax, %ss

    ; Far jump: specify segment selector and offset with $ prefixes
    ljmp $0x08, $.flush
.flush:
    ret

Here, ljmp $0x08, $.flush does the same job as the NASM version—$0x08 is the code segment selector, $.flush is the target offset.

3. MASM Syntax (common for Windows kernel development)

MASM requires the FAR PTR keyword to explicitly mark a far jump, with a similar segment:offset structure:

PUBLIC _gdt_flush
_gdt_flush PROC
    ; Retrieve GDT pointer from stack
    mov eax, [esp+4]
    lgdt [eax]

    ; Update data segments
    mov ax, 0x10
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    mov ss, ax

    ; Far jump with FAR PTR qualifier
    jmp FAR PTR 0x08:flush
flush:
    ret
_gdt_flush ENDP

The FAR PTR tells MASM this isn't a near jump, ensuring the CPU updates the CS register.

Quick Note

No matter which assembler you use, the core goal is the same: trigger a far jump to load your new code segment selector into CS. The exact syntax varies by toolchain, but the logic stays consistent.

内容的提问来源于stack exchange,提问作者user5930979

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 12:33:44