duskos

dusk os fork
git clone git://git.alexwennerberg.com/duskos
Log | Files | Refs | README | LICENSE

commit ddbe4c7fd773650c216c89c8d8de5358ab9bb856
parent d27c3be65ff94d7382ee81f21e05142a3e89e4ad
Author: Virgil Dupras <hsoft@hardcoded.net>
Date:   Thu, 21 Jul 2022 08:16:01 -0400

asm/i386: make all jumps relative

Instead of trying to shoehorn absolute jumps into the jmp, op, keep them all
as raw as possible (see comment in asm/i386) and keep that shoehorning for
another layer.

Diffstat:
Mfs/asm/i386.fs | 15++++++++++++---
Mfs/cc/vm.fs | 4++--
Mfs/tests/asm/i386.fs | 2+-
Mfs/xcomp/pc/mbr.fs | 6++++--
4 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/fs/asm/i386.fs b/fs/asm/i386.fs @@ -24,7 +24,6 @@ SZ32 value opsz 0 value imm \ value of current immediate, if set 0 value disp \ displacement value 0 value sib \ value of the SIB byte -0 value ORG \ base address for jmp, and call, rel32 computing \ Utilities : asm$ SZ32 to opsz 1 to opdirec 3 to opmod -1 to opreg -1 to oprm 0 to imm? ; @@ -139,8 +138,18 @@ AL _ al BL _ bl CL _ cl DL _ dl AH _ ah BH _ bh CH _ ch DH _ dh : op ( opcode -- ) doer c, does> ( a -- ) c@ c, asm$ ; $c3 op ret, +\ Jumps and relative addresses +\ i386 jumps and calls in their immediate modes are relative. We keep it that +\ way. However, those relative addresses are inconvenient to use because it's +\ relative to the *end* of the op, which can be 2, 3 or 5 bytes in size. This +\ makes it very inconvenient to use reliably because the caller has to be aware +\ of the size of its relative offset. To that end, we auto adjust that relative +\ address to the size of the op. Therefore, "0 jmp," is an infinite loop encoded +\ as EB FE. +: abs>rel ( a -- rel32 ) here - ; + \ Conditional jumps -: op ( opcode -- ) doer , does> ( rel32 a -- ) @ op, , ; +: op ( opcode -- ) doer , does> ( rel32 a -- ) @ op, 5 - , ; $840f op jz, $850f op jnz, \ JMP and CALL @@ -150,7 +159,7 @@ $840f op jz, $850f op jnz, \ the "opreg" for the modrm version. : op ( opcode -- ) doer , does> @ ( rel32? opcode -- ) opreg 0< if ( rel32 opcode ) - c, here - ORG + 4 - , asm$ + c, 5 - , asm$ else \ ( opcode ) 8 rshift opreg! $ff opmodrm, then ; diff --git a/fs/cc/vm.fs b/fs/cc/vm.fs @@ -218,7 +218,7 @@ operands value 'curop \ pop it with vmpspop, : vmcall, ( -- ) VM_*CONSTANT optype = if oparg VM_NONE optype! else opAsm then - call, opdeinit 0 to callsz ; + abs>rel call, opdeinit 0 to callsz ; \ Allocate a new register for active op and pop 4b from PS into it. : vmpspop, @@ -329,7 +329,7 @@ operands value 'curop : ]vmjmp ( 'jump_addr -- ) here over - 4 - swap ! ; : _ here 4 - ; -: vmjmp, ( a -- ) jmp, ; +: vmjmp, ( a -- ) abs>rel jmp, ; : vmjmp[, ( -- a ) 0 vmjmp, _ ; : vmjz, ( -- addr ) selop1 opAsm opAsm test, opdeinit diff --git a/fs/tests/asm/i386.fs b/fs/tests/asm/i386.fs @@ -21,7 +21,7 @@ foo2 1234 #eq \ test call in its different forms code foo3 - ' foo1 call, + ' foo1 abs>rel call, ax ' foo1 i) mov, ax call, ret, diff --git a/fs/xcomp/pc/mbr.fs b/fs/xcomp/pc/mbr.fs @@ -1,10 +1,12 @@ \ x86 bootloader ?f<< /asm/i386.fs -here to ORG here $200 0 fill +\ TODO: we're in 16bit real address mode, get out of it. +create ORG here $200 0 fill $26 jmp, \ bypass BPB $21 allot ax $0e58 i) mov, $10 int, -here jmp, +\ manually encoded 16bit infinite loop +$e9 c, $fd c, $ff c, $55 ORG $1fe + c!+ $aa swap c!