2011-11-07 22 views
6

Điều này cần được thực hiện trong quá trình lắp ráp thuần túy (ví dụ: không có thư viện hoặc cuộc gọi đến C).Xuất các số nguyên trong hội đồng trên Linux

Tôi hiểu bản chất của vấn đề: người ta cần chia số nguyên cho 10, chuyển đổi phần còn lại một chữ số thành ASCII, đầu ra và sau đó lặp lại quá trình với thương.

Nhưng vì lý do nào đó, nó không hoạt động. Tôi đang sử dụng NASM trên x86.

Dưới đây là những gì tôi có cho đến nay (bất cứ điều gì không đầu ra, nhưng không ném bất kỳ lỗi lắp ráp một trong hai):

; integer to output is stored in eax 
mov ecx, 10 ; for base 10 

loop: 
div ecx ;EAX contains the quotient, EDX the remainder 

; Do something to EDX to convert it to ASCII, not sure if this is correct 
add edx, '0' 

push eax ;We'll be playing with EAX to output EDX, save EAX to the stack 

mov eax, 4    ; sys_write 
mov ebx, 1    ; to STDOUT 
mov ecx, edx 
mov edx, 1 
int 0x80 

pop eax ;restore EAX 

cmp eax, 0 ;If EAX is 0, our job is done 
jnz loop 

Có một số câu hỏi tương tự với trang này (cụ thể là, thisthis), nhưng tôi bị mất trong quá trình triển khai. This question (cho DOS) cũng hữu ích, nhưng tôi vẫn còn bối rối.

Tôi phải thiếu điều gì đó ở đây. Suy nghĩ?

+0

Tôi không thấy hằng số '10' ở bất kỳ đâu trong mã này, điều này cần thiết để in ra các chữ số thập phân. (Bạn cần phải lặp lại 'div' và' mod' bằng '10', lưu trữ các chữ số, đảo ngược chúng, và xuất chúng. Hoặc đi từ 'đầu lớn' trước, và chia cho' 100,000,000', sau đó là '10.000.000' , v.v. - nhưng điều đó có thể không kém phức tạp hơn so với phương pháp lưu trữ và đảo ngược.) – sarnold

+0

@sarnold Quên để bao gồm một dòng ở trên cùng. Đã chỉnh sửa câu hỏi của tôi để thêm nó. –

+0

Tuyệt vời! Cảm ơn các cập nhật. – sarnold

Trả lời

3

Có ít nhất hai vấn đề nữa. ngoài tham nhũng của ecx rằng @sarnold đề cập:

  1. div ecx chia giá trị 64-bit edx:eax bởi ecx, vì vậy bạn cần đảm bảo rằng bạn thiết lập edx-0 trước khi chia.

  2. Đối số thứ hai cho cuộc gọi hệ thống write (trong ecx) phải là con trỏ tới bộ đệm chứa ký tự bạn muốn in, không phải ký tự.

Một cách để giải quyết vấn đề thứ hai là để thúc đẩy thanh ghi chứa các ký tự mà bạn muốn in trên stack, và sau đó gán con trỏ ngăn xếp esp để ecx (các điểm con trỏ ngăn xếp tại các mục gần đây nhất là đẩy và x86 lưu trữ các giá trị nhỏ, vì vậy byte đầu tiên là 8 bit thấp). ví dụ.

push edx   ; save value on stack 
mov eax, 4  ; sys_write 
mov ebx, 1  ; to STDOUT 
mov ecx, esp ; first byte on stack 
mov edx, 1  ; length = one byte 
int 0x80 
pop edx   ; remove what we pushed (or "add esp, 4" would do just as well here; 
       ;      we don't need the actual value again) 

Đó nên là đủ để có được một số lượng ...

(Nhưng vào thời điểm đó, bạn có thể nhận thấy một "tính năng" của thuật toán của bạn, và muốn suy nghĩ lại về cách bạn lưu trữ các chữ số được sản xuất bởi bộ phận!)

+0

Đây là một lời giải thích tuyệt vời, cảm ơn vì đã làm rõ nó. Khi bạn gợi ý, tôi hiểu tại sao thuật toán này in các số nguyên ngược lại. Bất kỳ suy nghĩ về sửa chữa đó? –

+1

Đặt một số không gian cho các chữ số (số nguyên 32 bit không dấu lớn nhất là 4294967295, vì vậy 10 byte là đủ), hoặc trong phần dữ liệu (ví dụ: sử dụng chỉ thị 'resb') hoặc trên ngăn xếp (chỉ trừ từ' esp' , nhưng chắc chắn rằng bạn trừ một bội số của 4 để giữ cho ngăn xếp được căn chỉnh đúng cách). Sau đó, lưu trữ các chữ số vào bộ đệm chuyển tiếp, sau đó lặp lại bộ đệm in ngược lại mỗi ký tự; hoặc (tốt hơn?) lưu trữ các chữ số vào bộ đệm bắt đầu từ byte cuối cùng của bộ đệm và làm việc ngược, sau đó bạn có thể viết tất cả các chữ số bằng một 's' 's' '' '' '' '' '' ' –

2

Bạn thiết lập đúng ecx-10 ở phía trên cùng của thói quen của bạn, nhưng ghi đè ecx sau:

mov eax, 4    ; sys_write 
mov ebx, 1    ; to STDOUT 
mov ecx, edx ;;; oops -- lost the 10 
mov edx, 1 
int 0x80 

Hãy thử di chuyển loop lên một dòng, vì vậy ecx được tái khởi tạo 10 mỗi lần thông qua các vòng lặp .

+0

Bắt tốt, sửa nó. Tôi vẫn không nhận được bất kỳ đầu ra nào, tôi đoán là 'add edx, '0'' không được chuyển đổi một cách chính xác thành chữ số thập phân. –

Các vấn đề liên quan