Assembly executing a long jump with an offset with different syntax

后端 未结 2 2119
被撕碎了的回忆
被撕碎了的回忆 2020-12-10 17:46

I am writing a GDT for a Kernel and all is going well, I\'m following this tutorial.

http://www.osdever.net/bkerndev/Docs/gdt.htm

When link the C code to the

相关标签:
2条回答
  • 2020-12-10 17:50

    A few things. The AT&T syntax for a far jump is:

    jmp $0x08,$flush2 
    

    The label in this case needs to be preceded by a $. Immediate values like 0x08 also need a $. This line doesn't do what you think it does:

    mov %ax, 0x10
    

    Important thing about AT&T syntax is that unlike Intel Syntax the operands are reversed. Source operand is first and destination operation is after. Secondly, immediate values in AT&T syntax on x86/x86-64 need to have a $ sign prepended to them or they are actually treated as a memory operand. Your instruction actually moved the 16-bit contents of AX to the memory address 0x00000010 which is not what you intended. What you wanted was:

    mov $0x10, %ax
    

    This moves the immediate value 0x10 to AX. The problem with operands being reversed also applies to all your lines like:

    mov %ds, %ax
    

    Should be:

    mov %ax, %ds
    

    I usually prefer calling your function load_gdt. I'm usually a fan of passing the segment values (CS and DS) and the address of the GDTR with code like:

    load_gdt:
        mov 4(%esp), %edx    # EDX is 1st argument - GDT record pointer
        mov 8(%esp), %eax    # EAX is 2nd argument - Data Selector
        lgdt (%edx)          # Load GDT with GDT record pointer passed as 1st argument
        mov %eax, %ds        # Reload all the data descriptors with Data selector (2nd arg)
        mov %eax, %es
        mov %eax, %gs
        mov %eax, %fs
        mov %eax, %ss
    
        pushl 12(%esp)      # Create FAR pointer on stack using Code selector (3rd argument)
        push $.setcs         # Offset of FAR JMP will be setcs label below
        ljmp *(%esp)        # Do the FAR JMP to next instruction to set CS with Code selector,
                            #    and set the EIP (instruction pointer) to offset of setcs
    .setcs:
        add $8, %esp        # Restore stack (remove 2 DWORD values we put on stack to
                            #     create FAR Pointer)
        ret
    

    The C prototype would be something like:

    void load_gdt(struct gdt_ptr *gdt_ptr, unsigned int data_sel, unsigned int code_sel);
    

    If you want to use GNU assembler with a variant of Intel Syntax you could try adding this directive to the top of all your assembly files:

    .intel_syntax noprefix
    
    0 讨论(0)
  • 2020-12-10 18:11

    In addition to Michael's answer, which definitely out-informs mine, this would be my translation:

    .global gdt_flush
    
    gdt_flush:
       movl 4(%esp),%eax
       lgdt (%eax)
    
       movw $0x10, %ax
       movw %ax, %ds
       movw %ax, %es
       movw %ax, %fs
       movw %ax, %gs
       movw %ax, %ss
       jmp  $0x08,$flush
    
    flush:
       ret
    
    0 讨论(0)
提交回复
热议问题