1

在汇编中,我们使用org指令将位置计数器设置为内存中的特定位置。这对于制作操作系统特别有用。这是一个示例引导加载程序(来自 wikibooks):

 org 7C00h

         jmp short Start ;Jump over the data (the 'short' keyword makes the jmp instruction smaller)

 Msg:    db "Hello World! "
 EndMsg:

 Start:  mov bx, 000Fh   ;Page 0, colour attribute 15 (white) for the int 10 calls below
         mov cx, 1       ;We will want to write 1 character
         xor dx, dx      ;Start at top left corner
         mov ds, dx      ;Ensure ds = 0 (to let us load the message)
         cld             ;Ensure direction flag is cleared (for LODSB)

 Print:  mov si, Msg     ;Loads the address of the first byte of the message, 7C02h in this case

                         ;PC BIOS Interrupt 10 Subfunction 2 - Set cursor position
                         ;AH = 2
 Char:   mov ah, 2       ;BH = page, DH = row, DL = column
         int 10h
         lodsb           ;Load a byte of the message into AL.
                         ;Remember that DS is 0 and SI holds the
                         ;offset of one of the bytes of the message.

                         ;PC BIOS Interrupt 10 Subfunction 9 - Write character and colour
                         ;AH = 9
         mov ah, 9       ;BH = page, AL = character, BL = attribute, CX = character count
         int 10h

         inc dl          ;Advance cursor

         cmp dl, 80      ;Wrap around edge of screen if necessary
         jne Skip
         xor dl, dl
         inc dh

         cmp dh, 25      ;Wrap around bottom of screen if necessary
         jne Skip
         xor dh, dh

 Skip:   cmp si, EndMsg  ;If we're not at end of message,
         jne Char        ;continue loading characters
         jmp Print       ;otherwise restart from the beginning of the message


 times 0200h - 2 - ($ - $$)  db 0    ;Zerofill up to 510 bytes

         dw 0AA55h       ;Boot Sector signature

 ;OPTIONAL:
 ;To zerofill up to the size of a standard 1.44MB, 3.5" floppy disk
 ;times 1474560 - ($ - $$) db 0

是否有可能用 C++ 完成任务?是否有任何命令、功能等,比如org我可以在哪里更改程序的位置?

4

2 回答 2

3

不,在我知道的任何 C 编译器中都不可能这样做。但是,您可以创建自己的链接描述文件,将代码/数据/bss 段放置在特定地址。

于 2013-08-30T07:13:30.903 回答
0

只是为了清楚起见,该org指令不会在指定地址加载代码,它只是通知汇编程序代码将在该地址加载。显示的代码似乎是针对 Nasm(或类似)的 - 在 AT&T 语法中,该.org指令做了一些不同的事情:它将代码填充到该地址 - 类似于timesNasm 代码中的行。Nasm 可以这样做,因为在-f bin模式下,它“充当它自己的链接器”。

代码要知道的重要事情是Msg可以找到的地址。jmps 和jnes (并且call您的ret示例没有,但编译器可能会生成)是相对寻址模式。我们编码jmp target,但实际发出的字节说jmp distance_to_target(加号或减号),所以地址无关紧要。

Gas 不会这样做,它会发出一个可链接的目标文件。要在没有链接器脚本的情况下使用 ld,命令行如下所示:

ld -o boot.bin boot.o -oformat binary -T text=0x7C00

(不要引用我的确切语法而是“类似的东西”)如果您可以从您的(16 位功能!)C++ 编译器中获得一个可链接的目标文件,您可能也可以这样做。

在引导扇区的情况下,代码由 BIOS(或假 BIOS)在 0x7C00 处加载——这是我们可以假设的关于引导扇区的少数几件事之一。对于 bootsector 来说,明智的做法不是在打印消息时摆弄,而是加载其他内容。您需要知道如何在磁盘上找到其他内容以及要将其加载到何处(可能是您的 C++ 编译器默认将其放置在何处)- 以及jmp那里。这jmp将是一个far jmp,它确实需要知道地址。

我猜这将是一些丑陋的C++!

于 2013-08-30T10:50:30.480 回答