จะลดขนาด EXE ของ x86 ASM ที่คอมไพล์ด้วย FASM ได้อย่างไร?


14

ในการออกกำลังกายฉันได้สร้างวิธีแก้ปัญหาง่ายๆสำหรับความท้าทายนี้ในภาษาแอสเซมบลี x86 ฉันกำลังใช้งาน FASM บน Windows นี่คือรหัสที่มาของฉัน:

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'

เมื่อฉันรวบรวมสิ่งนี้ฉันจะได้รับโปรแกรมที่ใหญ่กว่าที่ฉันคาดไว้ นี่คือ hexdump:

https://pastebin.com/W5sUTvTe

ฉันสังเกตเห็นว่ามีช่องว่างจำนวนมากระหว่างส่วนของรหัสและส่วนการนำเข้าข้อมูลและไลบรารีรวมถึงข้อความว่า "โปรแกรมนี้ไม่สามารถทำงานในโหมด DOS" ที่ฝังอยู่ในรหัส ฉันจะรวบรวมซอร์สโค้ดของฉันเป็นไฟล์ขนาดเล็กได้อย่างไรเหมาะสำหรับ Code Golf?

ในฐานะที่เป็นบันทึกย่อด้านคำแนะนำสำหรับวิธีที่ดีกว่าในการพิมพ์stdoutโดยไม่ต้องนำเข้าmsvcrtและการโทรprintfยินดีต้อนรับ


@iBug ฉันขอโทษที่ได้ยินเช่นนั้น คุณช่วยแนะนำสถานที่ที่เหมาะสมกว่าให้ฉันถามได้ไหม
vasilescur

12
@iBug เคล็ดลับคำถามที่ขอความช่วยเหลือในการเล่นกอล์ฟในบางกรณีนั้นไม่ได้อยู่นอกหัวข้อแน่นอน
AdmBorkBork


1
ต้องเป็น: start: push char Lb: call [printf] call [printf] call [printf] call [printf] inc [char] cmp [char], 'Z' jle Lb เพราะหากไม่สามารถใช้งานสแต็กได้ ; หนึ่งจะต้องดูว่าการเรียกร้องให้ printf หนึ่งแต่ละคนมีการเพิ่มการเรียนการสอนที่ปรับ ESP
RosLuP

1
แทน printf คุณสามารถ WriteFile (stdout) ต้องนำเข้าอื่น ๆ กว่า kernel32 ไม่มี (ซึ่งเป็นปัจจุบันโดยค่าเริ่มต้นคุณก็จำเป็นต้องตรวจสอบที่อยู่)
ปีเตอร์เฟอร์

คำตอบ:


2

เคล็ดลับทั่วไปค่อนข้างเล็กน้อย แต่

ใช้รูปแบบไฟล์ COM แทน PE EXE

PE EXE มีข้อบกพร่องเล็กน้อยทำให้รูปแบบไร้ประโยชน์ในการเขียนโค้ดกอล์ฟ ภาพแรกคือการจัดแนวรูปภาพ (Windows จะไม่เรียกใช้ไฟล์ EXE หากการจัดแนวไม่ถูกต้อง) และไฟล์ที่สองคือขนาดส่วนหัว มีปัจจัยบางอย่างที่ไม่สำคัญนี้ (แบ่งการปฏิบัติการออกเป็นส่วน ๆ )

ข้อดีของการใช้รูปแบบไฟล์ COM (ที่ค่อนข้างใกล้เคียงกับไบนารีแบบแบน) คือ:

  • รหัสส่วนหัวเป็นศูนย์, ไฟล์ไม่ได้แบ่งออกเป็นส่วนต่างๆ
  • ไม่มีการจัดแนวภาพ (ดังนั้นขนาดภาพอาจไม่สามารถหารด้วยพลังที่กำหนดไว้อย่างเข้มงวดของสองภาพ แต่จะต้องมีขนาดเล็กกว่า 65K แต่ก็ไม่ได้เปลี่ยนแปลงอะไรมากนักเพราะถ้าคุณส่งงานใหญ่กว่า 65K คุณก็กำลังทำอยู่ บางสิ่งผิดปกติ).
  • คุณไม่สามารถใช้ไลบรารีภายนอก - นี่เป็นข้อดีเพราะคุณไม่ต้องสงสัยเลยว่ามีวิธีอื่นในการทำ I / O นั่นคือสิ่งที่การขัดจังหวะ BIOS เป็นประโยชน์
  • คุณสามารถควบคุมหน่วยความจำและอุปกรณ์ที่เชื่อมโยงโดยตรงกับระบบได้โดยตรงดังนั้นจึงไม่มีเพจจิ้งไม่มีการละเมิดการเข้าถึงไม่มีการป้องกันหน่วยความจำไม่มีการทำงานพร้อมกันเป็นต้น ฟีเจอร์เหล่านี้ทำให้การเล่นกอล์ฟเป็นโปรแกรมที่สร้างสรรค์มากขึ้น

ฉันได้แก้ไขรหัสของคุณให้ทำงานเป็นเลขฐานสองแบบเรียบ มันง่ายมาก:

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, "$"

เอาต์พุตไบนารีมีขนาดใหญ่เพียง 32 ไบต์ ฉันเชื่อว่าเป็นไปได้ที่จะลดขนาดให้ใหญ่ยิ่งขึ้น แต่นี่เป็นเพียงจุดเริ่มต้น

nasm -fbin file.asm -o file.comประกอบกับ หมายเหตุตัวอย่างนี้ทำขึ้นสำหรับ NASM แต่คุณสามารถแปลได้อย่างอิสระเป็น FASM และมันจะทำงานได้อย่างไร้ที่ติ


ฉันไม่อยากจะเชื่อเลยว่าฉันได้ตอบคำถามนี้และกลับไปที่ google
Krzysztof Szewczyk
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.