2015-05-31 10 views
2

Я ударился головой о стену, пытаясь понять , почему следующий сборник неправильно сбросил содержимое «HELLO_WORLD».Сборка (x86): <label> db 'string', 0 не выполняется, если нет инструкции по прыжку

; Explicitly set 16-bit 
[ BITS 16 ] 
[ ORG 0x7C00 ] 

; Create label for hello world string terminated by null. 
HELLO_WORLD db 'hello world', 0 

start: 
    ; Move address of HELLO_WORLD into si 
    mov SI, HELLO_WORLD 
    call print_string 

    ; Continue until the end of time 
    jmp $ 

print_string: 
    loop: 
     ; Retrieve value stored in address at si 
     mov al, [SI] 
     mov ah, 0x0E 
     cmp al, 0 
     ; Finish execution after hitting null terminator 
     je return 
     INT 0x10 
     ; Increment contents of si (address) 
     inc SI 
     jmp loop 

    return: 
     ret 

; boot loader length *must* be 512 bytes. 
times 510-($-$$) db 0 
dw 0xAA55 

В конце концов, я обнаружил, что если мы не будем выполнять (сделать это не код) наклейку, то он функционирует правильно.

jmp start 
HELLO_WORLD db 'hello world',0  

Часть I найти наиболее запутанным, глядя на шестнадцатеричного дампа hello_world еще в двоичном (в начале - и кажется, нет никакого различия его типа).

кошка nojmp_boot.out

00000000 68 65 6c 6c 6f 20 77 6f 72 6c 64 00 be 00 7c e8 |hello world...|.| 
00000010 02 00 eb fe 8a 04 b4 0e 3c 00 74 05 cd 10 46 eb |........<.t...F.| 
00000020 f3 c3 eb e8 00 00 00 00 00 00 00 00 00 00 00 00 |................| 
00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 
000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.| 
00000200 

кошка jmpboot.out

00000000 eb 22 68 65 6c 6c 6f 20 77 6f 72 6c 64 00 be 02 |."hello world...| 
00000010 7c e8 02 00 eb fe 8a 04 b4 0e 3c 00 74 05 cd 10 ||.........<.t...| 
00000020 46 eb f3 c3 eb e8 00 00 00 00 00 00 00 00 00 00 |F...............| 
00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 
000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.| 
00000200 

Осматривая первые два байта, мы можем видеть 'e8 22' является shortjump для решения 22 (http://net.cs.uni-bonn.de/fileadmin/user_upload/plohmann/x86_opcode_structure_and_instruction_overview.pdf).

Мой вопрос:

Почему мы не можем иметь «hello_world» как часть выполнения программы, насколько я был обеспокоен, что не было никакого различия между кодом и данными?

Я использую следующие для компиляции:

nasm -f bin -o boot.bin boot.asm && if [ $(stat -c "%s" boot.bin) -ne 512 ]; then x; fi && qemu-system-x86_64 boot.bin 

ответ

4

Исполнение начинается в верхней части. Если вы опустите jmp start, тогда символ h будет интерпретироваться CPU так, как если бы это была инструкция. Неужели вы видите, что такое не может быть правильным?

Насколько я был заинтересован, не было никакого различия между кодом и данными?

Там нет никакого различия между кодом и данными, когда мы рассматриваем их размещения в двоичной системе. Но код и данные по-прежнему остаются 2 по-разному. Код является единственным, который может получить от.

+0

Большое спасибо user3144770. Из любопытства, есть ли какая-либо причина, по которой я не могу взять адрес HELLO_WORLD (так как это ярлык) и поместить его в регистр, который позже будет повторяться? (Я думаю, байтовый поток) –

+0

'mov si, HELLO_WORLD' уже делает то, что вы просите.(NASM синтаксис) –

+0

Проблема заключается в том, если я тогда попробуйте использовать: мов др, [SI] Он заканчивается на КСС ал, 0 JE возвратного –

2

С момента создания загрузочного сектора выполнение начинается с первого байта сгенерированного файла. Он не будет начинаться со стартовой метки или где-либо еще. Поскольку строка «hello world» находится в начале файла, эти байты - это то, что сначала выполняется. Эти байты интерпретируются процессором как инструкции, а не символы, и они выполняются как любые инструкции, которые они декодируют.

Вот инструкции, которые получают выполняются:

7c00: 68 65 6c    push 0x6c65 
7c03: 6c      ins BYTE PTR es:[di],dx 
7c04: 6f      outs dx,WORD PTR ds:[si] 
7c05: 20 77 6f    and BYTE PTR [bx+0x6f],dh 
7c08: 72 6c     jb  0x7c76 
7c0a: 64 00 be 00 7c   add BYTE PTR fs:[bp+0x7c00],bh 
7c0f: e8 02 00    call 0x7c14 
7c12: eb fe     jmp 0x7c12 
7c14: 8a 04     mov al,BYTE PTR [si] 
... 
+0

Спасибо - определенно имеет смысл. Также задал следующий вопрос: Из любопытства, есть ли какая-либо причина, по которой я не могу принять адрес HELLO_WORLD (так как это ярлык) и поместить его в регистр, а затем повторить? (Я думаю, байтовый поток) –