Làm cách nào để giảm kích thước EXE của x86 ASM được biên dịch bằng FASM?


14

Như một bài tập, tôi đã tạo ra một giải pháp đơn giản cho thử thách này , bằng Ngôn ngữ hội x86. Tôi đang chạy cái này với FASM trên Windows. Đây là mã nguồn của tôi:

format PE console
entry start

include 'WIN32A.inc'

section '.text' code executable
start:
    push    char            ; Start at 'A'
    call    [printf]        ; Print the current letter 4 times
    call    [printf]
    call    [printf]
    call    [printf]
    inc     [char]          ; Increment the letter
    cmp     [char], 'Z'     ; Compare to 'Z'
    jle     start           ; char <= 'Z' --> goto start

section 'r.data' data readable writeable
    char    db  'A', 10, 0  ; Stores the current letter

section '.idata' data readable import
    library  msvcrt,   'msvcrt.dll'
    import   msvcrt, printf, 'printf'

Khi tôi biên dịch cái này, tôi nhận được một tệp thực thi lớn hơn tôi mong đợi. Đây là một hexdump:

https://pastebin.com/W5sUTvTe

Tôi nhận thấy có rất nhiều khoảng trống giữa phần mã và phần nhập dữ liệu và thư viện, cũng như một thông báo "Chương trình này không thể chạy trong chế độ DOS" được nhúng trong mã. Làm cách nào tôi có thể tập hợp mã nguồn của mình thành một tệp nhỏ, phù hợp với Code Golf?

Là một lưu ý phụ, đề xuất cho các cách tốt hơn để in stdoutmà không cần nhập msvcrtvà gọi printfđược chào đón.


@iBug Tôi rất tiếc khi nghe điều đó. Bạn có thể vui lòng đề nghị một nơi phù hợp hơn cho tôi để hỏi?
vasilescur

12
@iBug Mẹo câu hỏi yêu cầu trợ giúp chơi gôn trong các trường hợp cụ thể chắc chắn không phải là lạc đề ở đây.
admBorkBork


1
Nó phải là: start: push char Lb: call [printf] call [printf] call [printf] call [printf] inc [char] cmp [char], 'Z' jle Lb vì nếu không, có thể tiêu thụ stack ; người ta phải xem nếu mỗi cuộc gọi đến printf, người ta phải thêm hướng dẫn điều chỉnh đặc biệt
RosLuP

1
thay vì printf, bạn có thể WriteFile (stdout), không cần nhập ngoại trừ kernel32 (hiện có theo mặc định, bạn chỉ cần xác định địa chỉ)
peter ferrie

Câu trả lời:


2

Một mẹo khá chung chung, nhưng

Sử dụng định dạng tệp COM thay vì PE EXE.

PE EXE có một vài sai sót khiến định dạng khá vô dụng trong môn đánh gôn. Đầu tiên là căn chỉnh hình ảnh (Windows sẽ không chạy tệp EXE nếu nó không được căn chỉnh chính xác) và thứ hai là kích thước tiêu đề. Có một vài yếu tố không quan trọng này (chia phần thực thi thành các phần).

Ưu điểm của việc sử dụng định dạng tệp COM (tương đương với nhị phân phẳng) là:

  • Không có mã tiêu đề, tệp không được chia thành các phần
  • Không căn chỉnh hình ảnh (vì vậy kích thước hình ảnh có thể không chia hết cho công suất được xác định nghiêm ngặt của hai, nhưng nó phải nhỏ hơn 65K. Mặc dù vậy, nó không thay đổi nhiều, vì nếu bài đăng của bạn lớn hơn 65K, bạn đang làm Có gì đó không đúng).
  • Bạn không thể sử dụng các thư viện bên ngoài - đây thực sự là một điểm cộng, bởi vì bạn chắc chắn có cách khác để thực hiện I / O. Đó là nơi mà các ngắt BIOS trở nên tiện dụng.
  • Bạn có quyền kiểm soát trực tiếp bộ nhớ và các thiết bị được liên kết với hệ thống, do đó không có phân trang, không vi phạm quyền truy cập, không bảo vệ bộ nhớ, không tương tranh, v.v. Những tính năng này làm cho nó dễ dàng hơn để chơi các chương trình thực sự sáng tạo.

Tôi đã sửa đổi mã của bạn để hoạt động như nhị phân phẳng. Thật đơn giản:

ORG 100H

MOV DX, P
MOV AH, 9

L:
    INT 21H
    INT 21H
    INT 21H
    INT 21H

    INC BYTE [P]
    CMP BYTE [P], 'Z'
    JLE L

MOV AX, 4C00h
INT 21h

P DB "A", 10, "$"

Nhị phân đầu ra chỉ là 32 byte lớn. Tôi tin rằng, có thể giảm kích thước hơn nữa, nhưng đây chỉ là điểm khởi đầu.

Lắp ráp với nasm -fbin file.asm -o file.com. Lưu ý, ví dụ này đã được tạo cho NASM, nhưng bạn có thể dịch nó tự do sang FASM, và nó sẽ hoạt động hoàn hảo.


Tôi không thể tin rằng tôi đã trả lời câu hỏi này và quay lại câu hỏi từ google
Krzysztof Szewchot
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.