Como reduzir o tamanho do EXE do x86 ASM compilado com o FASM?

14

Como exercício, criei uma solução simples para esse desafio, na linguagem Assembly x86. Estou executando isso com o FASM no Windows. Aqui está o meu código fonte:

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'

Ao compilar isso, obtenho um executável maior do que eu esperava. Aqui está um hexdump:

https://pastebin.com/W5sUTvTe

Percebo que há muito espaço vazio entre a seção de código e as seções de importação de dados e bibliotecas, bem como uma mensagem dizendo "Este programa não pode ser executado no modo DOS" incorporado no código. Como posso montar meu código-fonte em um arquivo pequeno, adequado para o Code Golf?

Como observação, sugestões de melhores maneiras de imprimir stdoutsem importar msvcrte ligar printfsão bem-vindas.

vasilescur
fonte
@iBug Lamento ouvir isso. Você poderia sugerir um lugar mais adequado para eu perguntar?
vasilescur
12
As dicas do @iBug Tips que solicitam ajuda com o golfe em casos específicos definitivamente não estão fora de tópico aqui.
AdmBorkBork
12
Meta relevante
AdmBorkBork
1
Tem que ser: start: push char Lb: call [printf] call [printf] call [printf] call [printf] inc [char] cmp [char], 'Z' jle Lb porque, se não, poderia consumir a pilha ; um tem que ver se cada chamada para um printf tem de adicionar a instrução que ajustar esp
RosLuP
1
em vez de printf, você pode WriteFile (stdout), necessitando de nenhum outro do que kernel32 importações (que está presente por padrão, você só precisa determinar o endereço)
peter ferrie

Respostas:

2

Dica bastante geral, mas

Use o formato de arquivo COM em vez do PE EXE.

O PE EXE possui algumas falhas, tornando o formato praticamente inútil no código-golfe. O primeiro é o alinhamento da imagem (o Windows não executa o arquivo EXE se não estiver alinhado corretamente) e o segundo é o tamanho do cabeçalho. Existem alguns fatores que não são tão importantes (dividindo o executável em seções).

As vantagens de usar o formato de arquivo COM (que é praticamente equivalente ao binário plano) são:

  • Zero código de cabeçalho, o arquivo não é dividido em seções
  • Sem alinhamento de imagem (portanto, o tamanho da imagem pode não ser divisível por uma potência estritamente definida de dois, mas deve ser menor que 65 K. Mas não muda muito, porque, se o envio for maior que 65 KB, você estará fazendo algo errado).
  • Você não pode usar bibliotecas externas - isso é realmente uma vantagem, porque sem dúvida você tem outra maneira de executar E / S. É aí que as interrupções do BIOS são úteis.
  • Você tem controle direto sobre a memória e os dispositivos vinculados ao sistema; portanto, não há paginação, violação de acesso, proteção de memória, simultaneidade etc. Esses recursos facilitam o golfe de programas realmente criativos.

Revisei seu código para funcionar como binário plano. É simples:

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

O binário de saída tem apenas 32 bytes de tamanho. Acredito, é possível reduzir ainda mais o tamanho, mas este é apenas um ponto de partida.

Monte com nasm -fbin file.asm -o file.com. Observe que este exemplo foi criado para o NASM, mas você pode traduzi-lo livremente para o FASM e ele funcionará perfeitamente.

Krzysztof Szewczyk
fonte
Não acredito que respondi a essa pergunta e voltei a ela do google
Krzysztof Szewczyk