Вы говорите «загрузитесь прямо в Windows», поэтому я предполагаю, что вы используете физический ПК. Замечание на будущее: всегда используйте эмулятор для разработки! Это просто проще Мне нравится Bochs для OSDeving, потому что он имеет хорошие функции отладки. Теперь о возможном решении.
Существует множество ошибочных BIOS, которые нарушают неофициальные спецификации IBM PC для адреса загрузки 0x7C00.
Это может вызвать много проблем с адресами памяти и т. Д. При сборке. Сделайте так, чтобы начало выглядело так:
[BITS 16] ;tell the assembler that its a 16 bit code
[ORG 0x7C00] ;this tells the assembler where the code will be loaded at when it runs on your machine. It uses this to compute the absolute addresses of labels and such.
jmp word 0:flush ;#FAR jump so that you set CS to 0. (the first argument is what segment to jump to. The argument(after the `:`) is what offset to jump to)
;# Without the far jmp, CS could be `0x7C0` or something similar, which will means that where the assembler thinks the code is loaded and where your computer loaded the code is different. Which in turn messes up the absolute addresses of labels.
flush: ;#We go to here, but we do it ABSOLUTE. So with this, we can reset the segment and offset of where our code is loaded.
mov BP,0 ;#use BP as a temp register
mov DS,BP ;#can not assign segment registers a literal number. You have to assign to a register first.
mov ES,BP ;#do the same here too
;#without setting DS and ES, they could have been loaded with the old 0x7C0, which would mess up absolute address calculations for data.
Видите, некоторая нагрузка на 0x07C0:0000
и большая нагрузка (и считается, что она соответствует) на 0x0000:7C00
. Это один и тот же плоский адрес, но разные настройки сегмента действительно могут испортить абсолютные адреса памяти. Итак, давайте удалим «магию» ассемблера и посмотрим, как это выглядит (обратите внимание, я не гарантирую, что адреса будут полностью корректными с этим. Я не знаю размер всех кодов операций)
jmp word 0:0x7C04 ;# 0x7C04 is the address of the `flush` label
...
Итак, мы переходим к абсолютному адресу.
Теперь тогда. Что происходит, когда мы этого не делаем?
возьмем эту программу, например:
mov ax,[mydata]
hlt
mydata: dw 500 ;#just some data
Это разбирает на что-то вроде
mov ax,[0x7C06]
О, ну, это использует абсолютную адресацию, так как это может пойти не так? Ну, а если DS на самом деле 0x7C0
? тогда вместо ожидаемого ассемблера 0:0x7C06
он получит 0x7C0:0x7C06
, которые не того же плоского адреса.
Надеюсь, это поможет вам понять. Это действительно сложная тема, и для ее полного понимания требуется некоторое время программирования низкого уровня.