AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / coding / Perguntas / 79549469
Accepted
Lion King
Lion King
Asked: 2025-04-02 09:23:34 +0800 CST2025-04-02 09:23:34 +0800 CST 2025-04-02 09:23:34 +0800 CST

Como posso chamar a função printf corretamente a partir do assembly?

  • 772

Estou tentando chamar uma função C x86, printf, em assembly, mas há um erro de vinculação: error LNK2019: unresolved external symbol _printf referenced in function _main.

.model flat, C
.code
extern printf: proc

main proc
    push offset msg
    push offset fmt
    call printf
    ret
main endp

.data
    msg db "Hello world!", 0
    fmt db "%s", 0
end

Como posso resolver esse problema?

windows
  • 3 3 respostas
  • 78 Views

3 respostas

  • Voted
  1. Best Answer
    RbMm
    2025-04-02T20:50:13+08:002025-04-02T20:50:13+08:00

    pode haver várias maneiras. se quiser usar bibliotecas existentes - _printfestava dentro legacy_stdio_definitions.lib, mas se usá-lo, também precisa vincular legacy_stdio_wide_specifiers.libe ucrt.lib, chamar __initterm(ou definir o ponto de entrada para _wmainCRTStartup) o código completo neste caso pode parecer

    .686
    
    .model flat
    
    extern _printf: PROC
    extern __imp__exit: DWORD
    extern __imp___initterm: DWORD
    
    .code
    
    ep proc
    
        push offset __xc_z
        push offset __xc_a
        call __imp___initterm
        add esp,8
        
        push offset msg
        push offset fmt
        call _printf
        add esp,8
        
        push eax
        call __imp__exit
        
        ret
    ep endp
    
    CRT$XIA SEGMENT ALIAS(".CRT$XIA")
    __xc_a DD 0
    CRT$XIA ENDS
    
    CRT$XIZ SEGMENT ALIAS(".CRT$XIZ")
    __xc_z DD 0
    CRT$XIZ ENDS
    
    .const
        msg db "Hello world!", 0
        fmt db "%s", 0
    end
    

    (observe que é melhor usar .consta seção .dataaqui para dados constantes)

    e linkar arquivo com

    
    link.exe /MAP /MERGE:.CRT=.rdata /SUBSYSTEM:CONSOLE /ENTRY:ep /LARGEADDRESSAWARE /DYNAMICBASE /MACHINE:X86 /SAFESEH:NO /OPT:REF /OPT:ICF /NODEFAULTLIB /EMITPOGOPHASEINFO /EMITVOLATILEMETADATA:NO /LIBPATH:"C:\lib\um\x86" /LIBPATH:"C:\msvc\lib\x86" /LIBPATH:"C:\lib\ucrt\x86" test.obj legacy_stdio_definitions.lib legacy_stdio_wide_specifiers.lib ucrt.lib
    

    outra maneira - construa meu próprio msvcrt.lib (o msvcrt.lib padrão não tem, printfapesar de ter sido exportado por msvcrt.dlle então use-o) maneira mínima

    
    .686
    .model flat
    API MACRO name
    name proc
    name endp
    ENDM
    .code
    API _printf
    end
    

    e msvcrt.def :

    EXPORTS
    printf
    

    construir com

    link.exe /DLL /NOENTRY:ep /LARGEADDRESSAWARE /DYNAMICBASE /MACHINE:X86 /SAFESEH:NO /OPT:REF /OPT:ICF /NODEFAULTLIB /EMITPOGOPHASEINFO /EMITVOLATILEMETADATA:NO /DEF:msvcrt.def msvcrt.obj
    

    e então pode usar isso

    .686
    
    .model flat
    
    extern __imp__printf: DWORD
    extern __imp__ExitProcess@4: DWORD
    
    .code
    
    ep proc
    
        push offset msg
        push offset fmt
        call __imp__printf
        add esp,8
        
        push eax
        call __imp__ExitProcess@4
        
        ret
    ep endp
    
    .const
        msg db "Hello world!", 0
        fmt db "%s", 0
    end
    

    link com:

    link.exe /MAP /SUBSYSTEM:CONSOLE /ENTRY:ep /LARGEADDRESSAWARE /DYNAMICBASE /MACHINE:X86 /SAFESEH:NO /OPT:REF /OPT:ICF /NODEFAULTLIB /EMITPOGOPHASEINFO /EMITVOLATILEMETADATA:NO /LIBPATH:"C:\lib\um\x86" /LIBPATH:"C:\msvc\lib\x86" /LIBPATH:"C:\lib\ucrt\x86" test2.obj msvcrt.lib kernel32.lib
    

    (maneira mais geral de autoconstruir biblioteca para dll - aqui )

    • 1
  2. rcgldr
    2025-04-02T15:45:01+08:002025-04-02T15:45:01+08:00

    Exemplo de código de 32 bits:

            .686p                   ;enable instructions
            .xmm                    ;enable instructions
            .model flat,c           ;use C naming convention (stdcall is default)
    
    ;       include C libraries
            includelib      msvcrtd
            includelib      oldnames
            includelib      legacy_stdio_definitions.lib    ;for scanf, printf, ...
    
            .data                   ;initialized data
    pfstr   db      "Hello world!",0dh,0ah,0
            .data?                  ;uinitialized data
            .stack  4096            ;stack (optional, linker will default)
    
            .code                   ;code 
            extrn   printf:near
            public  main
    
    main    proc
    
            push    offset pfstr
            call    printf
            add     esp,4 
    
            xor     eax,eax
            ret
    main    endp
    
            end
    

    Exemplo de código de 64 bits:

    ;       include C libraries
            includelib      msvcrtd
            includelib      oldnames
            includelib      legacy_stdio_definitions.lib    ;for scanf, printf, ...
    
            .data
    msg     db      "test",00dh,00ah,000h
            .code
            extern  printf:near
    
    main    proc
            sub     rsp,32                  ;caller allocates space for rcx,rcx,r8,r9
            lea     rcx,msg
            call    printf
            xor     eax,eax
            add     rsp,32
            ret
    main    endp
            end
    
    • 0
  3. slowdancer
    2025-04-02T13:47:48+08:002025-04-02T13:47:48+08:00

    Se você estiver usando o Windows, a mainfunção deve ser nomeada_main

    • -1

relate perguntas

  • C++ ReadFile inteiramente, onde tamanho> 2 GB (Win64)

  • BSOD do Windows Palo Alto Cortex XDR com verificação de bug 0x139

  • Não consigo importar pacotes locais no meu projeto go

  • O KERNEL32.DLL é sempre o terceiro módulo carregado em um processo do Windows?

  • Qual é o problema neste código Rust inseguro para que funcione no Windows, mas não no Ubuntu?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Reformatar números, inserindo separadores em posições fixas

    • 6 respostas
  • Marko Smith

    Por que os conceitos do C++20 causam erros de restrição cíclica, enquanto o SFINAE antigo não?

    • 2 respostas
  • Marko Smith

    Problema com extensão desinstalada automaticamente do VScode (tema Material)

    • 2 respostas
  • Marko Smith

    Vue 3: Erro na criação "Identificador esperado, mas encontrado 'import'" [duplicado]

    • 1 respostas
  • Marko Smith

    Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores?

    • 1 respostas
  • Marko Smith

    Como faço para corrigir um erro MODULE_NOT_FOUND para um módulo que não importei manualmente?

    • 6 respostas
  • Marko Smith

    `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso?

    • 3 respostas
  • Marko Smith

    Um programa vazio que não faz nada em C++ precisa de um heap de 204 KB, mas não em C

    • 1 respostas
  • Marko Smith

    PowerBI atualmente quebrado com BigQuery: problema de driver Simba com atualização do Windows

    • 2 respostas
  • Marko Smith

    AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos

    • 1 respostas
  • Martin Hope
    Fantastic Mr Fox Somente o tipo copiável não é aceito na implementação std::vector do MSVC 2025-04-23 06:40:49 +0800 CST
  • Martin Hope
    Howard Hinnant Encontre o próximo dia da semana usando o cronógrafo 2025-04-21 08:30:25 +0800 CST
  • Martin Hope
    Fedor O inicializador de membro do construtor pode incluir a inicialização de outro membro? 2025-04-15 01:01:44 +0800 CST
  • Martin Hope
    Petr Filipský Por que os conceitos do C++20 causam erros de restrição cíclica, enquanto o SFINAE antigo não? 2025-03-23 21:39:40 +0800 CST
  • Martin Hope
    Catskul O C++20 mudou para permitir a conversão de `type(&)[N]` de matriz de limites conhecidos para `type(&)[]` de matriz de limites desconhecidos? 2025-03-04 06:57:53 +0800 CST
  • Martin Hope
    Stefan Pochmann Como/por que {2,3,10} e {x,3,10} com x=2 são ordenados de forma diferente? 2025-01-13 23:24:07 +0800 CST
  • Martin Hope
    Chad Feller O ponto e vírgula agora é opcional em condicionais bash com [[ .. ]] na versão 5.2? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench Por que um traço duplo (--) faz com que esta cláusula MariaDB seja avaliada como verdadeira? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng Por que `dict(id=1, **{'id': 2})` às vezes gera `KeyError: 'id'` em vez de um TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos 2024-03-20 03:12:31 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve