我如何在汇编中的 FFFF0H 位置写入?

How I can write at a location FFFF0H in assembly?

我想在位置 FFFF0H 和目标 F8000H.

处写入一条 jmp 指令

之后,我想把下面的代码放在F8000H,这样在从FFFF0H执行时,控制权就会转移,通过上面的跳转,就可以了。

.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

备注

地址范围0F0000h-0FFFFFh是只读的。
真实的故事是,在创建 BIOS 的影子副本后,它在启动时被固件设置为只读,因此访问不必一直向下到 PCH,默认情况下重新路由它在标准地址范围 FFFF_0000H-FFFF_FFFFH

因此,这些地址范围要么映射到只读 DRAM 区域,要么映射到闪存 ROM,后者会在编程之前忽略写入请求。

如果您正在编写固件,那么构建链肯定支持创建可以放置在 ROM 中任何位置的部分。
解释如何使用此类工具超出了本答案和本网站的范围。


虽然您正在编写一个普通的 DOS 可执行文件,但请注意下面的解决方案不会工作。
因此,我将简单地假设您想要将一段代码从 A 移动到 B

我们需要:

  1. 在两个内存区域之间移动数据的一些代码。
    这可以通过多种方式完成,编码最快,但最慢(对于小块)是使用 rep movsbcx 字节从 ds:si 复制到 es:di

  2. 一种判断一段代码长度的方法。
    我们可以在代码段的开头和结尾分别放置两个标签,比如 SE。这样,表达式 E-S 给出了两个标签之间的差异(以字节为单位),即代码的长度。

这里是一个可能的实现:

.MODEL SMALL
.8086

.STACK

.DATA

.CODE

.STARTUP

 ;Set up ES
 mov ax, 0f000h
 mov es, ax

 ;Move the first routine 

 mov si, OFFSET __ROUTINE_1__START__                   ;DS:SI = Start of the routine to copy
 mov di, 8000h                                         ;ES:DI = 0f000h:8000h = 0f8000h
 mov cx,  __ROUTINE_1__END__ - __ROUTINE_1__START__    ;CX = Length of the routine to copy
 rep movsb

 ;Copy the jump

 mov si, OFFSET __ROUTINE_2__START__
 mov di, 0fff0h                                        ;ES:DI = 0f000h:0fff0h = 0ffff0h
 mov cx,  5                                            ;Absolute far jump is 5 bytes
 rep movsb


 ;DO SOMETHING HERE

 ;
 ; ROUTINE TO MOVE
 ;

__ROUTINE_1__START__:
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

__ROUTINE_1__END__:

__ROUTINE_2__START__:
 jmp FAR 0f000h:8000h                 ;TODO: Adjust the syntax for the assembler dialect

END

如我所说,此解决方案不适用于您选择的地址范围,除非您在特殊环境中工作。 我还假设您知道分段的工作原理。

我并没有直接通过 mov-immediate 存储机器码来创建 far jmp;相反,我让汇编程序创建机器代码,然后复制它。
它的效率较低,但可以让您轻松更改代码。