I want to write a jmp
instruction at the location FFFF0H and with destination F8000H.
After that, I want to place the code below at F8000H, so that upon execution from FFFF0H the control will be transferred, through the jump above, to it.
.MODEL SMALL
.8086
.STACK
.DATA
.CODE
.STARTUP
LL:
MOV AL, 1H
IO_LOOP:
OUT 0EH, AL
SHL AL, 1
;Delay
MOV CX, 0FFFFH
DLOOP:
NOP
LOOP DLOOP
;Start all over again
CMP AL, 00H
JE LL
;Get back to IO cycle
JMP IO_LOOP
END
Note
The address range 0F0000h-0FFFFFh is read only.
The true story is that it is set read-only by the firmware upon startup after the shadow copy of the BIOS has been made, so that an access doesn't have to go all the way down to the PCH, that by default reroute it at the standard address range FFFF_0000H-FFFF_FFFFH.
So those address range is either mapped to a read-only DRAM area or to a Flash ROM that ignores write requests until programmed.
If you are writing a firmware, then surely the build-chain supports the creation of sections that can be placed anywhere in the ROM.
Explaining how to use such tool is beyond the scope of this answer and this site.
It seems you are writing a normal DOS executable though, please note that the solution below will not work.
Hence-on I will simply assume that you want to move a piece of code from A to B.
We need:
Some code to move data between two memory region.
This can be done in many ways, the fastest to code, yet slowest (for small blocks) is the use of
rep movsb
that copycx
bytes fromds:si
toes:di
.A way to tell the length of a piece of code.
We can put two labels, say S and E, respectively at the start and at the end of the piece of code. This way the expression E-S gives the difference, in bytes, between the two labels, i.e. the length of the code.
Here a possible implementation:
As I said, this solution won't work for the address range you picked up, unless you are working in a special context. I also assumed you know how segmentation works.
I didn't create the far
jmp
directly by storing the machine code withmov
-immediate stores; instead I let the assembler create the machine code and then I copied it.It is less efficient but lets you change the code without much trouble.