2010-04-13 48 views
5

Tôi đã làm việc thông qua các hướng dẫn on this webpage để dần dần tạo bộ nạp khởi động hiển thị Hello World.Bộ tải khởi động Hello World không hoạt động

Hướng dẫn thứ hai (nơi chúng tôi cố gắng để có được "A" được xuất) hoạt động hoàn hảo, nhưng hướng dẫn đầu tiên không làm việc cho tôi cả! (BIOS hoàn toàn bỏ qua đĩa mềm và khởi động thẳng vào Windows). Đây là vấn đề ít hơn, mặc dù mọi giải thích sẽ được đánh giá cao.

Vấn đề thực sự là tôi không thể có được hướng dẫn thứ 3 để làm việc. Thay vì xuất hiện "Hello World", tôi nhận được một ký tự không bình thường (và con trỏ nhấp nháy) ở góc dưới cùng bên trái của màn hình. Nó trông giống như một khuôn mặt cười bên trong một hình chữ nhật tròn. Có ai biết làm thế nào để có được Hello World để hiển thị như nó phải không?

Trả lời

7

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:0x7C06khô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 đủ.

+0

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

+0

@Newbie yea cú pháp NASM của tôi là một chút thử gỉ 'jmp từ 0: bắt đầu ' – Earlz

+0

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

1

Tôi nghĩ rằng sự cố có thể liên quan đến nguồn gốc được chỉ định.

[ORG 0x7C00] ;Origin, tell the assembler that where the code will 

Dựa trên cuộc hội thoại, chúng tôi cho rằng địa chỉ này không được dự đoán theo một cách nào đó. Nó có thể chỉ đơn giản là DS đăng ký phân đoạn dữ liệu không phải là những gì bạn mong đợi. Bạn thực sự có thể có thể để có được danh sách ban đầu từ trang web hoạt động bằng cách thêm một push và pop của ds trước khi cuộc gọi để hiển thị chuỗi như thế này,

push cs 
pop ds 

Nếu không được đoạn mã sau hoạt động.

[ORG 0x000] ; switched to 0 since we are going to try to correct it ourself 

call nextinstruction 
nextinstruction: ; get the return address of the call into dx 
pop dx    ; which is essentially the start of the code + 3 (3 bytes for the call instruction) 
MOV SI, HelloString ;Store string pointer to SI 
add si, dx   ; add IP from start of program 
sub si, 3   ; subtract the 3 the call instruction probably took 
push cs 
pop ds    ; make ds the same as cs. 
CALL PrintString ;Call print string procedure 
JMP $  ;Infinite loop, hang it here. 

Mã này tính toán thời gian chạy của mã đang chạy và cũng đảm bảo DS trỏ đến cùng một phân đoạn. Trừ khi các hướng dẫn được ghi chú khác liên quan đến SI thường sử dụng DS làm phân đoạn mã của chúng để tham chiếu đến bộ nhớ.

DS là thanh ghi phân khúc và bạn có thể muốn đọc nội dung như số Art of Assembly để tìm hiểu thêm.

Earlz cũng đang làm điều tương tự, chỉ cần đảm bảo rằng thanh ghi chính xác để địa chỉ bộ nhớ được tham chiếu chính xác. Nó chỉ là anh ta biết nhiều hơn về đặc thù của ngành khởi động hơn tôi.

+0

Như tôi đã nói, hướng dẫn 2 hoạt động tốt, chứng minh rằng BIOS được thiết lập chính xác để khởi động từ đĩa mềm. Nó chỉ khi nó được yêu cầu làm NOTHING BUT HANG (hướng dẫn 1) rằng BIOS bỏ qua nó. Tôi phải trung thực tôi mới làm quen với toàn bộ điều khởi động này - hướng dẫn này là tất cả những gì tôi đã làm. Tôi cho rằng tôi * được * tải thông qua khu vực khởi động - điều gì khiến bạn nghĩ rằng tôi không? Ngoài ra, khi hướng dẫn hết hạn, chương trình được biên dịch bằng NASM thành một tệp nhị phân thô (không phải tệp COM). Nhưng tôi sẽ thử đề xuất của bạn. – DarkOwl

+0

Đúng, tôi đã hiểu sai những gì bạn nói. Trong trường hợp đó tôi nghi ngờ nguồn gốc vẫn là nguyên nhân của vấn đề, nhưng việc tìm ra nguyên nhân thực sự có thể yêu cầu in ra IP đăng ký để tìm ra nguồn gốc thực tế. Tôi sẽ xem tôi có thể tìm ra thứ gì đó để giúp đỡ không. –

+0

OK, tôi đã thử sugestion của bạn. Tôi vẫn không nhận được "Hello World", nhưng tôi cũng không nhận được một nhân vật bất thường nữa. Tôi chỉ đơn giản là có được một con trỏ nhấp nháy về phía trên bên trái (như trái ngược với góc dưới cùng, nơi mà các nhân vật bất thường trước đây đã được). – DarkOwl