Thứ Năm, 30 tháng 5, 2013

Cùng nhau phân tích một chương trình cộng trừ số nguyên 32-bit trong assembly

Tôi xin giới thiệu một chương trình nhỏ viết bằng assembly để cộng và trừ các số nguyên. Các thanh ghi (registers) được sử dụng để lưu giữ dữ liệu trung gian, chúng ta gọi các chương trình con từ thư viện (library subroutine) để hiển thị nội dung của các thanh ghi. Và đây là source code:

TITLE Add and Subtract (AddSub.asm)

; This program adds and subtracts 32-bit integers.

INCLUDE Irvine32.inc

.code
main PROC

mov eax, 10000h ; EAX = 10000h
add eax, 40000h ; EAX = 50000h
sub eax, 20000h ; EAX = 30000h
call DumpRegs ; display registers

exit
main ENDP
END main

Chúng ta sẽ lần lượt phân tích chương trình từng dòng một. Mỗi dòng của program code sẽ xuất hiện trước lời giải thích cho dòng đó.

    TITLE Add and Subtract        (AddSub.asm)

TITLE directive đánh dấu toàn bộ dòng này như là một comment. Bạn có thể đặt bất cứ thứ gì trên dòng này.

    ; This program adds and subtracts 32-bit integers.

Tất cả text phía bên phải của dấu chấm phải được assembler lờ đi, vì vậy tôi sử dụng nó cho comments.

    INCLUDE Irvine32.inc

INCLUDE directive sao chép tất cả các định nghĩa cần thiết và thông tin cài đặt từ một text file có tên là Irvine32.inc, đặt nó (các định nghĩa và thông tin) trong thư mục INCLUDE của assembler (việc mô tả file này sẽ được đề cập trong các bài viết sau này)

    .code

.code directive đánh dấu điểm bắt đầu của code segment, nơi tất cả các câu lệnh có thể thực thi được trong chương trình được đặt vào.

    main PROC

PROC directive nhận diện sự bắt đầu của một thủ tục (procedure). Một cái tên được chọn cho một thủ tục duy nhất trong chương trình của chúng ta là main.

    mov     eax, 10000h        ; EAX = 10000h

Lệnh MOV di chuyển (sao chép ) số nguyên 10000h đến thanh ghi EAX. Toán hạng đầu tiên (EAX) được gọi là toán hạng đích (destination operand), và toán hạng thứ hai được gọi là toán hạng nguồn (source operand). Comment phía bên tay phải hiển thị giá trị được mong đợi trong thanh ghi EAX.

    add    eax, 40000h         ; EAX = 50000h

Lệnh ADD cộng 40000h vào thanh ghi EAX. Comment hiển thị giá trị được mong đợi trong thanh ghi EAX.

    sub    eax, 20000h         ; EAX = 30000h

Lệnh SUB trừ giá trị thanh ghi EAX cho 20000h.

    call DumpRegs              ; hiển thị các thanh ghi

Câu lệnh CALL gọi một thủ tục để hiển thị các giá trị hiện hành của các thanh ghi CPU. Đây là một cách hữu dụng để xác minh xem chương trình có làm việc chính xác hay không.

             exit
    main   ENDP

Câu lệnh exit (gián tiếp ) gọi một hàm MS-Windows đã được định nghĩa để tạm ngưng chương trình.

ENDP directive đánh dấu kết thúc của thủ tục main.

Chú ý rằng exit không là một từ khóa của MASM; thay vào đó, nó là một macro command được định nghĩa trong  Irvine32.inc include file cung cấp một cách đơn giản để kết thúc chương trình.

    END    main

END directive đánh dấu dòng cuối của chương trình được assembled. Nó nhận dạng tên của thủ tục bắt đầu chương trình (program's startup procedure) (thủ tục bắt đầu thực thi chương trình)


Program Output

EAX = 00030000  EBX = 7FFDF000  ECX = 00000101  EDX = FFFFFFFF
ESI   = 00000000  EDI =  000000000  EBP = 0012FFF0  ESP  = 0012FFC4
EIP   = 00401024  EPL = 000000206  CF =0  SF = 0  ZF = 0  OF = 0  AF = 0  PF = 1

Hai dòng đầu của output hiển thị các giá trị hexadicimal của cách thanh ghi mục đích chung (general-purpose registers). EAX bằng 00030000h, giá trị được sinh ra bởi các lênh ADD và SUB trong chương trình. Giá trị của các thanh ghi mục đích chung khác là không quan trọng, bởi vì giá trị của chúng không được set bởi chương trình của chúng ta. Cột thứ 3 hiển thị giá trị của các thanh ghi EIP (con trỏ lệnh mở rộng) và EFL (các cờ mở rộng), cũng như là giá trị của các cờ Carry, Sign, Zero, Overfow, Auxilary Carry, và Parity.    

Không có nhận xét nào:

Đăng nhận xét