OSDev.org

The Place to Start for Operating System Developers
It is currently Fri Mar 29, 2024 6:07 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 11 posts ] 
Author Message
 Post subject: Give me PMode, or give me death
PostPosted: Sat Nov 24, 2007 7:42 pm 
Offline
User avatar

Joined: Sat Nov 24, 2007 7:25 pm
Posts: 5
I am using a bootloader to load my kernel from a floppy to 0x0100:0x0000, but I am having difficulties when switching to PMode (actually, I think it happens when making the far jump, to be more precise)...

The kernel code:
Code:
[BITS 16]
[ORG 0x0]

jmp start

;print
print:
push ax

.prn:
lodsb
or al,al
jz .end

mov ah,0eh
int 10h
jmp .prn

.end:
pop ax
ret

start:
    cli

    mov ax, 0x0100
    mov ss, ax          ;stack segment
    mov sp, 0xFFFF      ;stack pointer

    push cs
    pop ax
    mov dx,ax
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax

    sti

;start
begin:

    startmeup:
    mov si,starting
    call print
   
        cli                     ; Disable interrupts... again...

        xor ax, ax
        mov ds, ax              ; Set DS-register to 0 - used by lgdt
       
        lgdt [gdt_desc]         ; Load the GDT descriptor
       
        xor ax,ax
        mov ds,ax

        ;pmode in a can
        mov eax, cr0            ; Copy the contents of CR0 into EAX
        or eax, 1               ; Set bit 0
        mov cr0, eax            ; Copy the contents of EAX into CR0

        jmp 0x08:clear_pipe     ; Jump to code segment, offset clear_pipe


;old school Pmode tutorial for the sake of testing...
[BITS 32]                       
clear_pipe:
        mov ax, 10h             ; Save data segment identifyer
        mov ds, ax              ; Move a valid data segment into the data segment register
        mov ss, ax              ; Move a valid data segment into the stack segment register
        mov esp, 090000h        ; Move the stack pointer to 090000h

        ;write something
        mov byte [ds:0B8000h], 'P'      ; Move the ASCII-code of 'P' into first video memory
        mov byte [ds:0B8001h], 1Bh      ; Assign a color code


    cli  ; stop interrupts
    hlt ; halt the CPU


starting db 'Booting...',13,10,0


gdt:                    ; Address for the GDT

gdt_null:               ; Null Segment
        dd 0
        dd 0

gdt_code:               ; Code segment, read/execute, nonconforming
        dw 0FFFFh
        dw 0
        db 0
        db 10011010b
        db 11001111b
        db 0

gdt_data:               ; Data segment, read/write, expand down
        dw 0FFFFh
        dw 0
        db 0
        db 10010010b
        db 11001111b
        db 0

gdt_end:           

gdt_desc:                       ; GDT descriptor
        dw gdt_end - gdt - 1    ; Limit (size)
        dd gdt                 ; Address of the GDT



Bochs says:
Code:
00060434533i[BIOS ] Booting from 0000:7C00
00067385591e[CPU0 ] jump_protected: call gate.p == 0
00067385591e[CPU0 ] fetch_raw_descriptor: GDT: index (f007)1e00 > limit (53f0)
00067385591i[CPU0 ] protected mode
00067385591i[CPU0 ] CS.d_b = 16 bit
00067385591i[CPU0 ] SS.d_b = 16 bit
00067385591i[CPU0 ] EFER   = 0x00000000
00067385591i[CPU0 ] | RAX=0000000000000011  RBX=0000000000000007
00067385591i[CPU0 ] | RCX=0000000000000017  RDX=0000000000000100
00067385591i[CPU0 ] | RSP=000000000000ffff  RBP=0000000000000000
00067385591i[CPU0 ] | RSI=00000000ffff0107  RDI=0000000000080005
00067385591i[CPU0 ] |  R8=0000000000000000   R9=0000000000000000
00067385591i[CPU0 ] | R10=0000000000000000  R11=0000000000000000
00067385591i[CPU0 ] | R12=0000000000000000  R13=0000000000000000
00067385591i[CPU0 ] | R14=0000000000000000  R15=0000000000000000
00067385591i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf sf zf af PF cf
00067385591i[CPU0 ] | SEG selector     base    limit G D
00067385591i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
00067385591i[CPU0 ] |  CS:0100( 0004| 0|  0) 00001000 0000ffff 0 0
00067385591i[CPU0 ] |  DS:0000( 0005| 0|  0) 00000000 0000ffff 0 0
00067385591i[CPU0 ] |  SS:0100( 0005| 0|  0) 00001000 0000ffff 0 0
00067385591i[CPU0 ] |  ES:0100( 0005| 0|  0) 00001000 0000ffff 0 0
00067385591i[CPU0 ] |  FS:0100( 0005| 0|  0) 00001000 0000ffff 0 0
00067385591i[CPU0 ] |  GS:0100( 0005| 0|  0) 00001000 0000ffff 0 0
00067385591i[CPU0 ] |  MSR_FS_BASE:0000000000001000
00067385591i[CPU0 ] |  MSR_GS_BASE:0000000000001000
00067385591i[CPU0 ] | RIP=0000000000000084 (0000000000000084)
00067385591i[CPU0 ] | CR0=0x00000011 CR1=0x0 CR2=0x0000000000000000
00067385591i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
00067385591i[CPU0 ] >> jmp far 0008:0089 : EA89000800
00067385591e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown
status is 00h, resetting
00067385591i[SYS  ] bx_pc_system_c::Reset(SOFTWARE) called
00067385591i[APIC0] local apic in CPU 0 initializing
00067385591e[CPU0 ] CPU_LOOP bx_guard.interrupt_requested=1
Next at t=67385591


<bochs:2> dump_cpu
eax:0x00000000, ebx:0x00000000, ecx:0x00000000, edx:0x00000f20
ebp:0x00000000, esp:0x00000000, esi:0x00000000, edi:0x00000000
eip:0x0000fff0, eflags:0x00000002, inhibit_mask:0
cs:s=0xf000, dl=0x0000ffff, dh=0xff009bff, valid=1
ss:s=0x0000, dl=0x0000ffff, dh=0x00009300, valid=1
ds:s=0x0000, dl=0x0000ffff, dh=0x00009300, valid=1
es:s=0x0000, dl=0x0000ffff, dh=0x00009300, valid=1
fs:s=0x0000, dl=0x0000ffff, dh=0x00009300, valid=1
gs:s=0x0000, dl=0x0000ffff, dh=0x00009300, valid=1
ldtr:s=0x0000, dl=0x0000ffff, dh=0x00008200, valid=1
tr:s=0x0000, dl=0x0000ffff, dh=0x00008300, valid=1
gdtr:base=0x00000000, limit=0xffff
idtr:base=0x00000000, limit=0xffff
dr0:0x00000000, dr1:0x00000000, dr2:0x00000000
dr3:0x00000000, dr6:0xffff0ff0, dr7:0x00000400
cr0:0x00000010, cr1:0x00000000, cr2:0x00000000
cr3:0x00000000, cr4:0x00000000
done


If I execute this code instead of my bootloader (with the addition of 0AA55h as the boot signature, the 512b size adjustment and the ORG 7C00h directive), it works just fine and prints the blue P out on the screen.

I'm guessing that I haven't set up the GDT properly... How to make sure?
I tried adjusting the location of the GDT (since I am using ORG 0x0), but I still get a triple fault in Bochs:
Code:
gdt_desc:                       ; GDT descriptor
        dw gdt_end - gdt - 1    ; Limit (size)
        dd gdt + 0x1000       ; Address of the GDT + 0x1000


What next? Am I loading the GDT correctly? (am I pointing to it's location at all?)


Top
 Profile  
 
 Post subject:
PostPosted: Sun Nov 25, 2007 2:55 am 
Offline
Member
Member
User avatar

Joined: Sun Feb 18, 2007 7:28 pm
Posts: 1564
Code:
(am I pointing to it's location at all?)

Does not look like it.

The GDT itself looks fine. I personally would move the GDT into the 16bit code, and not the 32bit region though, as it is being addressed from the 16bit code.

This way, you can also keep ds=cs, and know it will point to the correct location.

_________________
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}


Top
 Profile  
 
 Post subject:
PostPosted: Sun Nov 25, 2007 7:12 am 
Offline
User avatar

Joined: Sat Nov 24, 2007 7:25 pm
Posts: 5
Tried moving the GDT to the 16bit section, but I still got the same error :(

Any more ideas I could try?


Top
 Profile  
 
 Post subject:
PostPosted: Sun Nov 25, 2007 7:24 am 
Offline
Member
Member

Joined: Mon Apr 09, 2007 12:10 pm
Posts: 775
Location: London, UK
Try a bit of basic bochs debugging. First, modify your program so you have a infinite loop immediately after the lgdt instruction, e.g.
Code:
lgdt [gdt_desc]
loop: jmp loop
Then run it and exit bochs. Note the value of IP (this is the address of the instruction after lgdt). Then, re-run bochs (with debugger enabled) and set a breakpoint at the location of IP you just found. Run the kernel. It will stop when the break point is hit. At this stage, you can use the 'info gdt' command to display the gdt. Note you need to give it a sensible range, e.g. 'info gdt 0 2'. This will see if the problem is in the gdt or elsewhere.

Regards,
John.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Nov 25, 2007 8:10 am 
Offline
User avatar

Joined: Sat Nov 24, 2007 7:25 pm
Posts: 5
If I put a "jmp $" after LGDT, Bochs says that I don't have any GDT entries:
Code:
<bochs:6> info gdt 0 5
Global Descriptor Table (base=0x0000000000f000ff, limit=21488):
GDT[0x00]=??? descriptor hi=0x00000000, lo=0x00000000
GDT[0x01]=??? descriptor hi=0x00000000, lo=0x00000000
GDT[0x02]=??? descriptor hi=0x00000000, lo=0x00000000
GDT[0x03]=??? descriptor hi=0x00000000, lo=0x00000000
GDT[0x04]=??? descriptor hi=0x00000000, lo=0x00000000
GDT[0x05]=??? descriptor hi=0x00000000, lo=0x00000000


If I do so after I have entered PMode, I get the same values (aka - nothing)!

However, if I just leave the whole thing to execute without interrupting it with endless loops, after the triple fault, I get these values:

Code:
<bochs:11> info gdt 0 5
Global Descriptor Table (base=0x0000000000000000, limit=65535):
GDT[0x00]=Code segment, linearaddr=f053f000, limit=0ff53 bytes, Execute/Read, Conforming, Accessed, 16-bit
GDT[0x01]=Code segment, linearaddr=f053f000, limit=0ff53 bytes, Execute/Read, Conforming, Accessed, 16-bit
GDT[0x02]=Code segment, linearaddr=f053f000, limit=0ff53 bytes, Execute/Read, Conforming, Accessed, 16-bit
GDT[0x03]=Code segment, linearaddr=f053f000, limit=0ff53 bytes, Execute/Read, Conforming, Accessed, 16-bit
GDT[0x04]=32-Bit TSS (Available) at 0xf087f000, length 0x0fea5
GDT[0x05]=Code segment, linearaddr=f053f000, limit=0ff53 bytes, Execute/Read, Conforming, Accessed, 16-bit

Which does not look like my GDT at all. (and there is a TSS present) Are these values generated during the triple fault, or...?


Top
 Profile  
 
 Post subject:
PostPosted: Sun Nov 25, 2007 10:53 am 
Offline
Member
Member

Joined: Mon Apr 09, 2007 12:10 pm
Posts: 775
Location: London, UK
I wouldn't give much consideration to what the command shows after the fault. One of the things you can guarantee with the bochs debugger is that debugging after a triple-fault is a pointless exercise. You need to interrupt execution sometime before the fault occurs to inspect the machine state. Looking at what happens after the gdt is loaded, you can see a rather large limit suggesting that the gdt is not correctly loaded. Also, the base is not right, it should be aligned on a 8 byte boundary (this is not critical, its just a performance issue) - NASM has the ALIGN keyword for this.

My guess is that the 6 byte value you're loading to gdtr is wrong. Basically, the label 'gdt' is given an address by nasm (if you're directly outputting binary) which is equal to its position within the file + the origin of that file (which is 0 as defined by [ORG 0x0]). Unfortunately, your kernel is not loaded at origin 0x0, but at 0x0100:0x0. This means that all segment-relative addresses work fine, but lgdt does not work on segment relative address, rather it works directly on linear addresses. That means that the 6 byte gdtr values are actually located at gdt_desc + 0x1000, and the gdt itself is located at gdt + 0x1000.

Doing something like
Code:
xor eax, eax
mov ax, cs
shl eax, 4
add [gdt + 2], eax
before lgdt should patch up the reference to add on the base of the code segment you are running in.

Regards,
John.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Nov 25, 2007 11:43 am 
Offline
User avatar

Joined: Sat Nov 24, 2007 7:25 pm
Posts: 5
Thanks for the reply John!

My new code follows:
Code:
[BITS 16]
[ORG 0x0]

jmp start

;print
print:
push ax

.prn:
lodsb
or al,al
jz .end

mov ah,0eh
int 10h
jmp .prn

.end:
pop ax
ret

start:
    cli

    mov ax, 0x0100
    mov ss, ax          ;stack segment
    mov sp, 0xFFFF      ;stack pointer

    push cs
    pop ax
    mov dx,ax
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax

    sti

;start
begin:

    startmeup:
    mov si,starting
    call print
   
        cli                     ; Disable interrupts... again...

        xor ax, ax
        mov ds, ax              ; Set DS-register to 0 - used by lgdt
       
        lgdt [gdt_desc+0x1000]         ; Load the GDT descriptor
       
        xor ax,ax
        mov ds,ax

        ;pmode in a can
        mov eax, cr0            ; Copy the contents of CR0 into EAX
        or eax, 1               ; Set bit 0
        mov cr0, eax            ; Copy the contents of EAX into CR0

jmp $

        jmp 0x08:clear_pipe     ; Jump to code segment, offset clear_pipe


;old school Pmode tutorial for the sake of testing...
[BITS 32]                       
clear_pipe:
        mov ax, 10h             ; Save data segment identifyer
        mov ds, ax              ; Move a valid data segment into the data segment register
        mov ss, ax              ; Move a valid data segment into the stack segment register
        mov esp, 090000h        ; Move the stack pointer to 090000h

        ;write something
        mov byte [ds:0B8000h], 'P'      ; Move the ASCII-code of 'P' into first video memory
        mov byte [ds:0B8001h], 1Bh      ; Assign a color code


    cli  ; stop interrupts
    hlt ; halt the CPU


starting db 'Booting...',13,10,0

[BITS 16]
gdt:                    ; Address for the GDT

gdt_null:               ; Null Segment
        dd 0
        dd 0

gdt_code:               ; Code segment, read/execute, nonconforming
        dw 0FFFFh
        dw 0
        db 0
        db 10011010b
        db 11001111b
        db 0

gdt_data:               ; Data segment, read/write, expand down
        dw 0FFFFh
        dw 0
        db 0
        db 10010010b
        db 11001111b
        db 0

gdt_end:           

gdt_desc:                       ; GDT descriptor
        dw gdt_end - gdt - 1    ; Limit (size)
        dd gdt + 0x1000                ; Address of the GDT


OK, so, apparently, adjusting the location of the GDT by adding linear 0x1000 so that LGDT can load it did the trick:

Code:
<bochs:90> info gdt 0 5
Global Descriptor Table (base=0x0000000000001123, limit=23):
GDT[0x00]=??? descriptor hi=0x00000000, lo=0x00000000
GDT[0x01]=Code segment, linearaddr=00000000, limit=fffff * 4Kbytes, Execute/Read, 32-bit
GDT[0x02]=Data segment, linearaddr=00000000, limit=fffff * 4Kbytes, Read/Write

There's the null segment and the code and data segments, with their attributes correctly displayed.

However, when I remove the "jmp $" before I do a far jump, Bochs triple faults:

Code:
00899281591i[CPU0 ] LOCK prefix unallowed (op1=0x53, attr=0x0, mod=0x0, nnn=0)
00899281591i[CPU0 ] protected mode
00899281591i[CPU0 ] CS.d_b = 32 bit
00899281591i[CPU0 ] SS.d_b = 16 bit
00899281591i[CPU0 ] EFER   = 0x00000000
00899281591i[CPU0 ] | RAX=0000000000000011  RBX=0000000000000007
00899281591i[CPU0 ] | RCX=00000000000000ff  RDX=0000000000000100
00899281591i[CPU0 ] | RSP=000000000000ffff  RBP=0000000000000000
00899281591i[CPU0 ] | RSI=00000000ffff010d  RDI=0000000000080005
00899281591i[CPU0 ] |  R8=0000000000000000   R9=0000000000000000
00899281591i[CPU0 ] | R10=0000000000000000  R11=0000000000000000
00899281591i[CPU0 ] | R12=0000000000000000  R13=0000000000000000
00899281591i[CPU0 ] | R14=0000000000000000  R15=0000000000000000
00899281591i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf sf zf AF PF cf
00899281591i[CPU0 ] | SEG selector     base    limit G D
00899281591i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
00899281591i[CPU0 ] |  CS:0008( 0001| 0|  0) 00000000 000fffff 1 1
00899281591i[CPU0 ] |  DS:0000( 0005| 0|  0) 00000000 0000ffff 0 0
00899281591i[CPU0 ] |  SS:0100( 0005| 0|  0) 00001000 0000ffff 0 0
00899281591i[CPU0 ] |  ES:0100( 0005| 0|  0) 00001000 0000ffff 0 0
00899281591i[CPU0 ] |  FS:0100( 0005| 0|  0) 00001000 0000ffff 0 0
00899281591i[CPU0 ] |  GS:0100( 0005| 0|  0) 00001000 0000ffff 0 0
00899281591i[CPU0 ] |  MSR_FS_BASE:0000000000001000
00899281591i[CPU0 ] |  MSR_GS_BASE:0000000000001000
00899281591i[CPU0 ] | RIP=000000000000008f (000000000000008f)
00899281591i[CPU0 ] | CR0=0x00000011 CR1=0x0 CR2=0x0000000000000000
00899281591i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
00899281591i[CPU0 ] >> lock push ebx : F053
00899281591e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown
status is 00h, resetting
00899281591i[SYS  ] bx_pc_system_c::Reset(SOFTWARE) called
00899281591i[APIC0] local apic in CPU 0 initializing
00899281591e[CPU0 ] CPU_LOOP bx_guard.interrupt_requested=1
Next at t=899281591
(0) [0x0000008f] 0008:008f (unk. ctxt): lock push ebx             ; f053


I added a "jmp $" right after clear_pipe:, but the same problem occurs.
"lock push ebx" is not present in my code, so I'm guessing I have jumped to the wrong position... have I?


Top
 Profile  
 
 Post subject:
PostPosted: Sun Nov 25, 2007 12:06 pm 
Offline
Member
Member

Joined: Mon Apr 09, 2007 12:10 pm
Posts: 775
Location: London, UK
Yep, same issue again. You're now in pmode, with cs having a base of 0, rather than 0x1000 like it did in real mode. Unfortunately, you loaded your kernel to 0x1000. Therefore you need to add 0x1000 to the address you jump to (clear_pipe). edit: please try jmp 0x8:clear_pipe+0x1000 first, otherwise
Code:
mov eax, clear_pipe
add eax, 0x1000
push 0x8
push eax
retf
should work. As far as I remember, the jmp opcode can't be encoded with something like jmp 0x8:eax, so you need to push the values to the stack and far return to them. Please set up a protected mode stack first, though.

The alternative way is to set up a second section within your binary file that is reserved for 32-bit code, e.g.
Code:
[BITS 16]
[ORG 0x0]
... 16-bit code ...

TIMES 0x100-($-$$) db 0

section .code32
[BITS 32]
[ORG 0x1100]
... 32-bit code ...
then all addresses in the 32 bit section have 0x1000 added to them anyway, so you don't need to mess around with changing pointers. If you were to include the gdt bits in here as well, then they would work without needing to change the gdt base. This assumes your 16-bit code fits in 0x100 (=256 bytes). Change the TIMES 0x100 line if you need more, and set ORG 0x1100 to ORG (0x1000 + whatever) as necessary. I assume this would work, its just off the top of my head without any testing.

Regards,
John.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Nov 25, 2007 1:34 pm 
Offline
User avatar

Joined: Sat Nov 24, 2007 7:25 pm
Posts: 5
Can't do retf, bochs reports that the CS selector is null... If I try a far jump to 0x08:eax, the kernel acts strangely, printing out a data value from the bootloader (probably stuck in a weird place).

Code:
87287767598e[CPU0 ] return_protected: CS selector null
87287767598i[CPU0 ] protected mode
87287767598i[CPU0 ] CS.d_b = 16 bit
87287767598i[CPU0 ] SS.d_b = 16 bit
87287767598i[CPU0 ] EFER   = 0x00000000
87287767598i[CPU0 ] | RAX=000000000000109a  RBX=0000000000000007
87287767598i[CPU0 ] | RCX=000000000000f000  RDX=0000000000000100
87287767598i[CPU0 ] | RSP=000000000000fff9  RBP=0000000000000000
87287767598i[CPU0 ] | RSI=00000000ffff011a  RDI=0000000000080005
87287767598i[CPU0 ] |  R8=0000000000000000   R9=0000000000000000
87287767598i[CPU0 ] | R10=0000000000000000  R11=0000000000000000
87287767598i[CPU0 ] | R12=0000000000000000  R13=0000000000000000
87287767598i[CPU0 ] | R14=0000000000000000  R15=0000000000000000
87287767598i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf sf zf af PF cf
87287767598i[CPU0 ] | SEG selector     base    limit G D
87287767598i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
87287767598i[CPU0 ] |  CS:0100( 0004| 0|  0) 00001000 0000ffff 0 0
87287767598i[CPU0 ] |  DS:0000( 0005| 0|  0) 00000000 0000ffff 0 0
87287767598i[CPU0 ] |  SS:0100( 0005| 0|  0) 00001000 0000ffff 0 0
87287767598i[CPU0 ] |  ES:0100( 0005| 0|  0) 00001000 0000ffff 0 0
87287767598i[CPU0 ] |  FS:0100( 0005| 0|  0) 00001000 0000ffff 0 0
87287767598i[CPU0 ] |  GS:0100( 0005| 0|  0) 00001000 0000ffff 0 0
87287767598i[CPU0 ] |  MSR_FS_BASE:0000000000001000
87287767598i[CPU0 ] |  MSR_GS_BASE:0000000000001000
87287767598i[CPU0 ] | RIP=0000000000000099 (0000000000000099)
87287767598i[CPU0 ] | CR0=0x00000011 CR1=0x0 CR2=0x0000000000000000
87287767598i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
87287767598i[CPU0 ] >> retf  : CB
87287767598e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown
status is 00h, resetting
87287767598i[SYS  ] bx_pc_system_c::Reset(SOFTWARE) called
87287767598i[APIC0] local apic in CPU 0 initializing
87287767598e[CPU0 ] CPU_LOOP bx_guard.interrupt_requested=1
Next at t=87287767598
(0) [0x00001099] 0100:0099 (unk. ctxt): retf                      ; cb


As for the second solution, NASM won't let me change the ORG value again:
Code:
error: program origin redefined


So, I did a jmp 0x08:clear_pipe+0x1000, and it worked :)
Cheers, John!


Top
 Profile  
 
 Post subject:
PostPosted: Sun Nov 25, 2007 2:53 pm 
Offline
Member
Member
User avatar

Joined: Wed Oct 18, 2006 3:45 am
Posts: 9301
Location: On the balcony, where I can actually keep 1½m distance
You can't link parts of an assembly file to different locations with just NASM. Either, you set the base of CS and DS to the same values as they are used in real mode, or you use two binaries and have your first load the second one from disk.

_________________
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]


Top
 Profile  
 
 Post subject:
PostPosted: Sun Nov 25, 2007 4:58 pm 
Offline
Member
Member

Joined: Mon Apr 09, 2007 12:10 pm
Posts: 775
Location: London, UK
Combuster wrote:
You can't link parts of an assembly file to different locations with just NASM.
NASM's manual (6.1.1) seemed to suggest you can
NASM manual wrote:
6.1.1 ORG: Binary File Program Origin
...
Its sole function is to specify one offset which is added to all internal address references within the section
as long as you use separate sections within the file. Still, as I said, I hadn't tested it and I guess the OP proved me wrong :cry:

Regards,
John.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 11 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: cloudapio, ErenJaeger, Majestic-12 [Bot] and 148 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group