Ir para conteúdo

Problema em gerar executável no Windows - PoC Aprendendo Assembly


Paulo Ferr

Posts Recomendados

Olá,

Estou estudando Assembly no Windows pelo livro Aprendendo Assembly e para gerar um aqruivo objeto em NASM eu envio este comando:

nasm assembly.asm -f win64

o que gera um arquivo assembly.obj. Entretanto não consigo linkar com o main.o do arquivo C para gerar o executável final. Envio o print da mensagem de erro para tentar obter alguma ajuda.

 

print.png

Link para o comentário
Compartilhar em outros sites

  • 4 meses depois...
Em 30/09/2021 em 13:48, Paulo Ferr disse:

Olá,

Estou estudando Assembly no Windows pelo livro Aprendendo Assembly e para gerar um aqruivo objeto em NASM eu envio este comando:

nasm assembly.asm -f win64

o que gera um arquivo assembly.obj. Entretanto não consigo linkar com o main.o do arquivo C para gerar o executável final. Envio o print da mensagem de erro para tentar obter alguma ajuda.

 

print.png

Conseguiu resolver o problema? também estou passando por ele..

 

Link para o comentário
Compartilhar em outros sites

3 horas atrás, Fernando Mercês disse:

Envia o código também, pra gente dar uma olhada. ?

 

Olá Fernando, o código que utilizei foi o do próprio tutorial:

bits 64

global assembly
assembly:
  mov eax, 777
  ret

O objeto é criado, mas não dá pra linkar com o main.o; pesquisei sober o error e, se entendi corretamente, o problema seria no arquivo assembly, a sua estrutura.

Link para o comentário
Compartilhar em outros sites

Olha, eu não tenho certeza, mas acho que o NASM requer símbolos globais começando com underscore. De qualquer forma, como você tá usando o gcc, acho que ele vai buscar a main. Então tenta aí:

bits 64

global main

main:
  mov eax, 777
  ret

Ou tenta com _main ao invés de main (altera nos dois lugares).

Boa sorte!

Link para o comentário
Compartilhar em outros sites

3 horas atrás, Fernando Mercês disse:

Ah, você pode tentar linkar com o ld também:

ld -o assembly assembly.obj

 

Eu não estava conseguindo fazer a montagem e executar o arquivo Fonte Assembler na minha máquina, então eu fiz um simples programinha em C, que soma 2 variáveis e coloca numa terceira variável, depois apresenta na tela o resultado. 

Com o programa pronto, executei o seguinte comando: gcc -S -m32 main.c  e gerei um arquivo main.s.

Depois fiz: gcc -o main_asm -m32 main.s que gerou um main_asm.exe (executavel) e funcionou !!!

Porém ... o arquivo teste.s, ao abri-lo, notei que o formato está diferente do NASM, está no GAS, incluindo umas diretivas do CFI que não compreendo bem

 ? 

Programa teste.s:

    .file    "main.c"
    .def    ___main;    .scl    2;    .type    32;    .endef
    .section .rdata,"dr"
LC0:
    .ascii "Resultado: %d\12\0"
    .text
    .globl    _main
    .def    _main;    .scl    2;    .type    32;    .endef
_main:
LFB10:
    .cfi_startproc
    pushl    %ebp
    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8
    movl    %esp, %ebp
    .cfi_def_cfa_register 5
    andl    $-16, %esp
    subl    $32, %esp
    call    ___main
    movl    $5, 28(%esp)
    movl    $3, 24(%esp)
    movl    28(%esp), %edx
    movl    24(%esp), %eax
    addl    %edx, %eax
    movl    %eax, 20(%esp)
    movl    20(%esp), %eax
    movl    %eax, 4(%esp)
    movl    $LC0, (%esp)
    call    _printf
    movl    $0, %eax
    leave
    .cfi_restore 5
    .cfi_def_cfa 4, 4
    ret
    .cfi_endproc
LFE10:
    .ident    "GCC: (MinGW.org GCC-6.3.0-1) 6.3.0"
    .def    _printf;    .scl    2;    .type    32;    .endef

 

 

Minha dúvida está em como fazer a sintaxe do NASM funcionar ao fazer o processo de montagem e, como tirar as diretivas do CFI pela sintaxe GAS.

PS1: O NASM foi instalado corretamente, consigo ver a versão pelo CMD, bem como ver as instruções do comando usando nasm -h.

PS2: Como modifiquei o programa original, não faço uso de função externa, tenho somente um arquivo e por isso não fiz processo de linkar ainda.

Link para o comentário
Compartilhar em outros sites

Em 04/02/2022 em 22:02, Fernando Mercês disse:

Não acho que dê. Que eu saiba, o NASM não suporta a sintaxe da AT&T usada pelo GAS. Eu insistiria no seu exemplo anterior com o ld mesmo. ?

Abraço.

Consegui resolver o problema, muito obrigado Fernando ?

Poderia me ajudar só com mais uma dúvida ?

Estou trabalhando com a sintaxe AT&T e tenho esses dados que imprime um simples "Hello word!" :

    .file    "hello.c"
    .def    ___main;    .scl    2;    .type    32;    .endef
    .section .rdata,"dr"
LC0:
    .ascii "Hello World!\0"
    .text
    .globl    _main
    .def    _main;    .scl    2;    .type    32;    .endef
_main:
    pushl    %ebp
    movl    %esp, %ebp
    andl    $-16, %esp
    subl    $16, %esp
    call    ___main
    movl    $LC0, (%esp)
    call    _printf
    movl    $0, %eax
    leave
    ret
    .ident    "GCC: (MinGW.org GCC-6.3.0-1) 6.3.0"
    .def    _printf;    .scl    2;    .type    32;    .endef

Estou estudando a movimentação na stack, mas não entendo essa chamada recursiva do próprio main.

Onde está em negrito, são referencia para o mesmo Main, neste caso _main ou __main é diferente de _main?

Link para o comentário
Compartilhar em outros sites

Em 06/02/2022 em 11:39, Fernando Mercês disse:

É outro label sim, porque tem dois underscores. Mas não vejo onde ele está sendo definido. Talvez esteja vazio? Como fica no binário depois de assemblado?

Abraço!

Nunca gerei um binário antes, procurei na internet e achei esse código: xxd -b hello.o | less, porém removi o less e concatenei num arquivo dessa forma forma:

xxd -b hello.o > binario.txt  

logo abaixo deixei o arquivo binário, mas não consegui identificar os labels referidos anteriormente, nem se o __main esta de fato executando algo...

 

binario.txt

Link para o comentário
Compartilhar em outros sites

Opa, quando a gente fala "binário" é em referência ao arquivo executável (ou biblioteca), mas não precisa dar a saída em sistema binário de numeração não. ?

Na verdade a melhor saída pra ver isso é com um disassembler, então você pode ou anexar o arquivo aqui (hello.o) ou postar a saída do seguinte comando:

$ objdump -d hello.o

Valeu!

Link para o comentário
Compartilhar em outros sites

1 hora atrás, Fernando Mercês disse:

Opa, quando a gente fala "binário" é em referência ao arquivo executável (ou biblioteca), mas não precisa dar a saída em sistema binário de numeração não. ?

Na verdade a melhor saída pra ver isso é com um disassembler, então você pode ou anexar o arquivo aqui (hello.o) ou postar a saída do seguinte comando:

$ objdump -d hello.o

Valeu!

Estava lendo sobre engenharia reversa e percebi que entendi errado XD, deixo abaixo o txt com o formato adequado. Muito mais legivel kkkk. Um está com sintaxe NASM e outro GAS, mas são o mesmo "Hello world". Obrigado por mencionar o Disassembler.

Achei o __Main, ele não é uma função vazia, porém ele armazena segmento de dado (407028) em eax e depois faz um test eax, eax. Ainda está obscuro para mim essas "movimentações" e manipulação da memória ?

Esqueci de avisar que estou no Windows, porém estou usando o Git Bash e manipulando os arquivos como se fosse Linux, foi o jeito que achei para seguir o tutorial.

 Livro excelente sobre Assembly ?

binario.txt binario2.txt

Link para o comentário
Compartilhar em outros sites

O fato de você estar compilando com gcc no Windows pelo Git Bash faz com que várias coisas sejam adicionadas no binário final, por conta do MinGW (Minimalist GNU for Windows). Fica mais complicado aprender assim. Eu recomendaria usar nasm e ld somente, de preferência num Linux virtual, ou via WSL2.

Outra opção é usar ferramentas nativas para Windows. Aí recomendaria o fasm.

Mas o livro é muito bom mesmo, então segui-lo como o autor propõe é a melhor recomendação, creio. ?

Abraço.

Link para o comentário
Compartilhar em outros sites

 

Em 10/02/2022 em 10:37, Fernando Mercês disse:

O fato de você estar compilando com gcc no Windows pelo Git Bash faz com que várias coisas sejam adicionadas no binário final, por conta do MinGW (Minimalist GNU for Windows). Fica mais complicado aprender assim. Eu recomendaria usar nasm e ld somente, de preferência num Linux virtual, ou via WSL2.

Outra opção é usar ferramentas nativas para Windows. Aí recomendaria o fasm.

Mas o livro é muito bom mesmo, então segui-lo como o autor propõe é a melhor recomendação, creio. ?

Abraço.

Agradeço muito pelo apoio e as dicas, certamente me ajudaram muito. Irei montar uma maquina virtual e analisar os resultados posteriormente ?

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

  • 1 ano depois...
Em 30/09/2021 em 12:48, Paulo Ferr disse:

Olá,

Estou estudando Assembly no Windows pelo livro Aprendendo Assembly e para gerar um aqruivo objeto em NASM eu envio este comando:

nasm assembly.asm -f win64

o que gera um arquivo assembly.obj. Entretanto não consigo linkar com o main.o do arquivo C para gerar o executável final. Envio o print da mensagem de erro para tentar obter alguma ajuda.

 

print.png

Ola devs, tbm estou passando por esse problema, iniciei em Assembly e ainda nao consegui gerar o executavel, tentei as opções do forum e nenhuma deu certo! Fernando um help pfv. Segue abaixo os codigos:

[assembly.asm]

bits 64

global main

main:

  mov eax, 777

  ret

=================================

[main.c]

#include <stdio.h>

int assembly(void);

int main(void){

    printf("Resultado: %d \n", assemby());

    return 0;

}

===============

Tentei todas as opções!

 

 



 

Link para o comentário
Compartilhar em outros sites

Em 25/03/2023 em 12:26, Emir_Fadul disse:

Ola devs, tbm estou passando por esse problema, iniciei em Assembly e ainda nao consegui gerar o executavel, tentei as opções do forum e nenhuma deu certo! Fernando um help pfv. Segue abaixo os codigos:

[assembly.asm]

bits 64

global main

main:

  mov eax, 777

  ret

=================================

[main.c]

#include <stdio.h>

int assembly(void);

int main(void){

    printf("Resultado: %d \n", assemby());

    return 0;

}

===============

Tentei todas as opções!

 

 



 

Desculpa a demora para responder. Bom, indo direto ao ponto: houve um erro meu e um seu aqui, rsrsrs. Repare que no seu arquivo 'assembly.asm' você definiu o rótulo como `main`, não é como está no código de exemplo passado no livro. Lá o nome do rótulo é `assembly` e não `main`. O nome do rótulo, não coincidentemente, é o mesmo da função invocada no código em C.

O meu erro é que faltou um `section .text` no código em Assembly, por isso o erro de "undefined reference" no Windows (no Linux esse erro não acontece, sei lá porquê).

Eu já atualizei as instruções no livro com a correção do código do 'assembly.asm' e adicionei os comandos de como compilar no Windows (só para garantir). O código, após a correção, ficou assim:

bits 64

section .text

global assembly
assembly:
  mov eax, 777
  ret

Se você verificar o livro novamente e seguir as instruções atualizadas, deve funcionar dessa vez.

Nota: Fiz os testes usando uma máquina virtual do Windows 7, MinGW-w64 versão 12.2.0-rt_v10-rev2 e NASM versão 2.16.01.

Valeu por me marcar @Fernando Mercês.

Link para o comentário
Compartilhar em outros sites

Participe da conversa

Você pode postar agora e se cadastrar mais tarde. Se você tem uma conta, faça o login para postar com sua conta.

Visitante
Responder

×   Você colou conteúdo com formatação.   Remover formatação

  Apenas 75 emojis são permitidos.

×   Seu link foi automaticamente incorporado.   Mostrar como link

×   Seu conteúdo anterior foi restaurado.   Limpar o editor

×   Não é possível colar imagens diretamente. Carregar ou inserir imagens do URL.

  • Quem Está Navegando   0 membros estão online

    • Nenhum usuário registrado visualizando esta página.
×
×
  • Criar Novo...