IRC channel logs

2024-01-29.log

back to list of logs

<damo22>WOOT
<damo22> CS =0008 00000000 ffffffff 00c09b00 DPL=0 CS32 [-RA]
<damo22>...
<damo22> GDT= 00007150 00000017
<damo22>dang it works for paragraph 0 but not if the paragraph is >0
<damo22>or segment 0
<damo22>it works for 0x7000 but not if the address > 0xffff
<anatoly>solid_black: all done, repo is up-to-date and the new image is uploaded
<sneek>anatoly, you have 1 message!
<sneek>anatoly, solid_black says: I've pushed my recent work, please try re-bootstrapping it
<anatoly>sneek: thanks a lot!
<youpi>damo22: addresses are 16bit, yes
<youpi>so you need to use the paragraph number to go further than 64k
<youpi>actually I was thinking about it: ip very probably has to be 0 at AP boot anyway
<youpi>otherwise it wouldn't work above 64k
<youpi>i.e. cs is just set to the proper paragraph and ip set to 0
<youpi>you could as well just copy over cs into ds
<youpi>and use the offset from "apboot:" as address for lgdt etc.
<damo22>that does not work
<damo22>i can load the gdt as you say, but then the ljmp fails
<damo22>have a look at my latest commit here, which works if apboot_addr is set to something less than 0xffff: https://git.zammit.org/gnumach-sv.git/commit/?h=fix-ioapic&id=4cef8c0cf0fb7b32011ba9ba8ce77840388d0baa
<damo22> (qemu) p $eip
<damo22> 0x2
<damo22>CS =1100 00011000 0000ffff 00009b00
<damo22>that is the realmode start
<damo22>if i load the gdt at 0x130 it crashes
<damo22>no, my bad, its the ljmp that crashes
<damo22>i dont understand segmentation in real mode obviously
<damo22>0x00011000 is what address in real mode? is it seg:0x11 offset 0x0 ?
<rrq>isn't such a segment = 16 bytes? .. making the segment index 0x1100
<youpi>damo22: in real mode, adress = segment*16 + offset
<youpi>that was explained in the stackoverflow answer I mentioned the other day
<youpi>so 0x11000 can be reached by 0x1100:0x0 or 0x1000:0x1000 for instances
<youpi>your code is overly complex, you don't actually need to do relocation
<youpi>after copying cs into ds, you can just load lgdt from that
<youpi>using gdt_descr_tmp-apboot as address
<youpi>since in your segment where you live, apboot is at address 0
<youpi>i.e. do *not* set ds to 0
<youpi>setting ds to 0 would mean you have to compute the full address, but you don't actually need that
<youpi>in the ljmp case, you can compute the absolute adress, with xorl %eax,%eax; mov %cs,%ax ; shl $4,%eax; add $0f - apboot, %eax; ljmp $BOOT_CS, (%eax); 0: .code32 movlw $BOOT_DS, %ax etc.
<youpi>(since $BOOT_CS will have been configured by lgdt to use absolute addresses)
<youpi>(sorry for having said the other day that you could use a variable filled the boot page address etc., I was mislead by the existing code that uses a fixed address for now actual good reason)
<youpi>s/now/no/
<damo22>i think ljmp instruction takes a 16 bit immediate not a 32 bit address
<youpi>damo22: ah, for the ljmp, indeed, then for the ljmpl it'd be 32bit
<damo22>unless there is a hand crafted asm instruction i can use in real mode to pass a 32 bit address?
<damo22>gas is broken for 16 bit
<damo22>If the operand-size is 32 or 64 bits, the operand is a 16-bit selector followed by a 32-bit offset
<damo22> https://i2.paste.pics/QAKDD.png
<damo22>Far Jumps in Real-Address or Virtual-8086 Mode. When executing a far jump in real-address or virtual-8086 mode, the processor jumps to the code segment and offset specified with the target operand. Here the target operand specifies an absolute far address either directly with a pointer (ptr16:16 or ptr16:32) or indirectly with a memory location (m16:16 or m16:32). With the pointer method, the segment and address of the called procedure is
<damo22>encoded in the instruction, using a 4-byte (16-bit operand size) or 6-byte (32-bit operand size) far address immediate. With the indirect method, the target operand specifies a memory location that contains a 4-byte (16-bit operand size) or 6-byte (32-bit operand size) far address. The far address is loaded directly into the CS and EIP registers. If the operand-size attribute is 16, the upper two bytes of the EIP register are cleared to 0s
<damo22>i should not use the 0xff based instructions, because they are limited to pentium or higher i think
<youpi>you want to use the far one, to load the cs
<youpi>that's actually the point of this jmp
<damo22>yes
<youpi>so as to switch to a 32bit segment
<damo22>but gas wont let me compile the instruction
<youpi>how so?
<damo22>addr32 ljmp $BOOT_CS, M(0f)(%eax)
<damo22>../i386/i386/cpuboot.S: Assembler messages:
<damo22>../i386/i386/cpuboot.S:139: Error: operand type mismatch for `ljmp'
<youpi>possibly it's not supported to ljmp through %eax
<youpi>since 0xEA alone doesn't tell whether it's an absolute address or via a register
<damo22>but i need to store the value in a register?
<youpi>alternatively you can relocate from the C code
<youpi>so that the instruction indeed uses immediates
<youpi>or make the code write %eax to a variable and use the variable with indirect jmp
<damo22>what if i just use .byte 0xea ; .word 0 ; .long 0
<youpi>(the address comes before the segment)
<damo22>or try intel syntax
<youpi>intel syntax won't be grokked by gas
<damo22>.syntax intel
<damo22>jmp 0000:00000000
<youpi>yes, you can use .byte 0xea; jmp_addr: .long address ; .long $KERNEL_CS
<youpi>and change jmp_addr from the C code
<youpi>what is the point of using the intel syntax?
<damo22>because you can specify the segment:offset
<youpi>you can do that with the gnu syntax
<youpi>jmp $0, $0
<damo22>ok
<youpi>ljmp $0,$0 actually
<youpi>but still you want to change the address so you want to have a label pointing to the $0 address
<youpi>thus encoding by hand, to be able to relocate from C code
<damo22>right
<youpi>or use a variable
<youpi>the variable approach would probably be simpler, to compute the offsets from within the .S file instead of doing it from the C file
<damo22>yes
<damo22>.code16
<damo22>.byte 0xea
<damo22>.long 0xabcd1234
<damo22>.word 0x8
<damo22> 0: ea 34 12 cd ab ljmp $0xabcd,$0x1234
<damo22> 5: 08 00 or %al,(%bx,%si)
<youpi>that's what you'd expect, yes
<damo22>is the objdump -M i8086 wrong?
<youpi>yes
<youpi>not a problem
<damo22>ugh
<youpi>.code16 is not encoded in the binary
<youpi>so the tools have *no* way to know whether it's 16bit or 32bit
<damo22>yes but i told objdump to force 16 bit parsing
<youpi>well, it did parse 16bit
<youpi>using the 16b 0x1234 address
<damo22>so how does the cpu know to use the rest of the 0x0008 ?
<youpi>it depends on the size of the current loadedsegment
<damo22>i dont believe tat
<damo22>.code16
<damo22>.byte 0x66
<damo22>.byte 0xea
<damo22>.long 0xabcd1234
<damo22>.word 0x8
<damo22> 0: 66 ea 34 12 cd ab 08 ljmpl $0x8,$0xabcd1234
<damo22>i think 0x66 is a modifier that allows you to force 32 bit
<youpi>you can also use a modifier to change it, yes
<damo22>c108fd54: 66 ea ljmpl $0x8,$0xffffffff
<damo22>c108fd5b:
<damo22>c108fd56 <ljmp_offset32>:
<damo22>c108fd56: ff (bad)
<damo22>c108fd57: ff (bad)
<damo22>c108fd58: ff (bad)
<damo22>c108fd59: ff
<damo22>:D
<etno>Usually, for 16 bit asm, gas uses whatever instruction it likes, even if they are available only on post 386, prepending a 32bits modifier. That is why people keep using bcc and watcom for true 16 bits dev
<damo22>CS =0008 00000000 ffffffff 00c09b00 DPL=0 CS32 [-RA]
<damo22>GDT= 00011140 00000017
<damo22>looks good!
<damo22> (qemu) xp $edx
<damo22> 000000000108fd60: 0x0010b866
<etno>This is the perfect moment for the Van Halen song : Jump!
<damo22>booted to rump
<damo22>still crashes on AMD bare metal
<damo22>this was frustrating to code, but its probably better now
<damo22>ljmpl $0x8, $0xabcdef <-- this assembles... gah
<damo22>but i guess i still needed the manual instruction to relocate it