Vì vậy, tôi đang học x86 Linux với cú pháp NASM (Ôi trời, không phải lần này, bạn đều đang suy nghĩ). Tôi đang cố gắng để làm cho một chương trình con sẽ chỉ đơn giản là in giá trị trong EAX để stdout. Mã chạy và thoát mà không có lỗi, nhưng không có gì in. Tôi không thể hiểu tại sao. Trước hết, đây là file tôi đang làm việc tại:Linux x86 NASM - Chương trình con: In từ dword từ EAX
segment .bss
to_print: resd 1
segment .text
global print_eax_val
print_eax_val: ; (top)
push dword ebx ;Stack: edx
push dword ecx ; ecx
push dword edx ; ebx
; (bot)
mov ecx,eax ;ecx = eax
mov [to_print],ecx ;to_print = ecx
mov eax, 4 ;sys_write
mov ebx, 1 ;to stdout
add ecx, 47 ;add 47 for ASCII numbers
mov edx, 2 ;double word = 2 bytes
int 0x80
mov eax, [to_print] ;eax = original val
pop edx ;pop the registers back from the stack
pop ecx
pop ebx ;Stack: empty
ret
này được gọi là từ tập tin chính của tôi, trông như thế này (điều này có lẽ không thích hợp, trừ khi tôi đang thiếu một cái gì đó mạnh mẽ).
segment .data
hello db "Hello world!", 0
newline db 0xA
len equ $ - hello
len2 equ $ - newline
segment .text
extern print_nl
extern print_eax_val
global main
main:
enter 0,0
call print_nl
mov eax, 1
call print_eax_val
mov ebx, 0 ;exit code = 0 (normal)
mov eax, 1 ;exit command
int 0x80 ;ask kernel to quit
print_nl
chỉ là một chương trình con khác định nghĩa và in dòng mới. Điều này chạy thành công và in một dòng mới như mong đợi.
Sự cố có liên quan đến thông số độ dài cho lệnh gọi sys_write
của tôi không? Tôi tặng nó 2, có kích thước là dword
, đó là kích thước của cả thanh ghi EAX
và nhãn to_print
của tôi, mà tôi đã đặt trước với resd 1
. Tôi đã cố gắng thay đổi độ dài thành 1, 4, 8, 16 và 32 trong tuyệt vọng ... Không có gì hiệu quả.
EDIT: Đối với những ai đang tự hỏi, đây là cách tôi cố định mã: (Tôi sẽ đặt dấu hoa thị trên các tuyến đường mà tôi đã thay đổi):
segment .bss
to_print: resd 1
segment .text
global print_eax_val
print_eax_val: ; (top)
push dword ebx ;Stack: edx
push dword ecx ; ecx
push dword edx ; ebx
; (bot)
mov ecx,eax ;ecx = eax
mov [to_print],ecx ;to_print = ecx
**** add dword [to_print], 48
mov eax, 4 ;sys_write
mov ebx, 1 ;to stdout
**** mov ecx, to_print
mov edx, 2
int 0x80
**** sub dword [to_print], 48
mov eax, [to_print] ;eax = original val
pop edx ;pop the registers back from the stack
pop ecx
pop ebx ;Stack: empty
ret
Về cơ bản, ecx
phải chứa địa chỉ của khối bạn muốn in, KHÔNG phải giá trị của chính nó. Như được chỉ ra trong câu trả lời đã chọn, điều này sẽ chỉ chỉ hoạt động nếu eax nằm trong khoảng 0-9.
CHỈNH SỬA 2: Vì vậy, tôi hơi bối rối về tham số thứ 2 cho sys_write (số được lưu trữ trong edx
). Tôi nghĩ nó chỉ đề cập đến một số byte. Vì vậy, đối với một dword
, như tôi đã sử dụng, nó sẽ là thích hợp để sử dụng 4 ở đó, bởi vì một từ kép là 4 byte, hoặc 32 bit. Tôi đoán nó làm việc vì x86 là một người rất ít tuổi. Vì vậy, trong bộ nhớ, giá trị hex của to_print
sẽ trông như thế này:
90 00 00 00
Và với chiều dài cung cấp hai, sys_write được:
90 00
Vì vậy, giá trị may mắn không bị hỏng.
sau, tôi đã thay đổi mã để lưu trữ to_print
như một byte thay vào đó, sử dụng resb 1
và truy cập nó bằng cách sử byte
thay vì dword
... Một byte là tốt ở đây, bởi vì tôi biết tôi sẽ không để cho to_print
một giá trị trên 9.
Cảm ơn rất nhiều! Câu trả lời của bạn rất hữu ích. Vâng, tôi nhận ra điều này sẽ chỉ làm việc cho 0 đến 9, tôi chỉ cố gắng để có được một số vấn đề cơ bản. Có lẽ tôi sẽ bắt đầu với một số mảng/con trỏ int-to-string kinh doanh cuối cùng. Tôi sẽ chỉnh sửa bài đăng của mình bằng mã được cập nhật, cho bất kỳ ai khác muốn biết. –
Tôi hoan nghênh bạn vì đã giải quyết ngôn ngữ lắp ráp và chúc bạn may mắn. BTW, câu hỏi của bạn là một câu hỏi SO nguyên mẫu tốt. Bạn đã cung cấp chính xác thông tin cần thiết, cho thấy những gì bạn đã thử và hỏi một câu hỏi cụ thể. +1 –
Cảm ơn một lần nữa, và tôi chắc chắn sẽ phân loại câu trả lời của bạn thành câu trả lời "nguyên mẫu tốt". Tôi quyết định tìm hiểu một số x86 lắp ráp sau khi một lớn C + + segfault/con trỏ meltdown trong một dự án tôi đang làm việc trên. Trước hết, đó là một sự chuyển hướng tốt đẹp, thứ hai, tôi muốn biết tôi thực sự * đang làm gì khi viết mã. –