Bạn nói "khởi động thẳng vào cửa sổ" vì vậy tôi cho rằng bạn đang sử dụng PC thực. Lưu ý trong tương lai để thực hiện: Luôn sử dụng trình giả lập để phát triển! Nó dễ dàng hơn. Tôi thích Bochs cho OSDeving vì nó có tính năng gỡ lỗi tốt đẹp. Bây giờ, vào giải pháp có thể.
Có rất nhiều BIOS lỗi phá vỡ các thông số kỹ thuật không chính thức của máy tính IBM cho địa chỉ tải 0x7C00.
Điều này có thể gây ra nhiều vấn đề với địa chỉ bộ nhớ và như vậy bất cứ khi nào bạn lắp ráp. Vì vậy, hãy bắt đầu trông như thế này:
[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.
Xem, một số phụ tải tại 0x07C0:0000
và tải nhất (và coi là phù hợp để) tại 0x0000:7C00
. Đó là cùng một địa chỉ phẳng, nhưng các thiết lập phân đoạn khác nhau có thể thực sự vít lên các địa chỉ bộ nhớ tuyệt đối. Vì vậy, hãy loại bỏ các "ma thuật" của lắp ráp và xem những gì nó trông giống như (lưu ý tôi không đảm bảo địa chỉ để được hoàn toàn đúng với điều này. Tôi không biết kích thước của tất cả các opcodes)
jmp word 0:0x7C04 ;# 0x7C04 is the address of the `flush` label
...
Vì vậy, , chúng tôi chuyển đến một địa chỉ tuyệt đối.
Bây giờ, sau đó.Điều gì xảy ra khi chúng ta không làm điều này?
đưa chương trình này ví dụ:
mov ax,[mydata]
hlt
mydata: dw 500 ;#just some data
này disassembles một cái gì đó giống như
mov ax,[0x7C06]
Oh, tốt nó sử dụng địa chỉ tuyệt đối, vậy làm thế nào có thể mà đi sai? Vâng, nếu DS thực sự là 0x7C0
thì sao? sau đó thay vì nhận được bộ lắp ráp dự kiến 0:0x7C06
, nó sẽ nhận được 0x7C0:0x7C06
là không cùng một địa chỉ bằng phẳng.
Tôi hy vọng điều này sẽ giúp bạn hiểu. Nó thực sự là một chủ đề phức tạp mặc dù và mất một thời gian của chương trình cấp thấp để hiểu đầy đủ.
Xin chào, cảm ơn bạn đã trả lời. Thật không may mã của bạn không đúng về mặt cú pháp trong NASM. Nó nói với tôi rằng có một sự không phù hợp trong kích thước toán hạng (??) trên dòng bắt đầu "jmp FAR 0x0000 ...". Tuy nhiên, cảm ơn cho lời cảm ơn emulator. – DarkOwl
@Newbie yea cú pháp NASM của tôi là một chút thử gỉ 'jmp từ 0: bắt đầu ' – Earlz
Chỉ cần cài đặt Bochs và khởi động mã hướng dẫn ban đầu vào nó. Mẫu mã từng hướng dẫn hiện hoạt động! Câu hỏi đặt ra là BIOS của tôi không phải là tiêu chuẩn hay là mã? (Chắc chắn tất cả các BIOS tương thích x86 phải tuân thủ các tiêu chuẩn tương tự ???) Tôi sẽ thử bản sửa đổi của bạn trên máy tính của tôi BIOS vật lý. – DarkOwl