Problem Linking (win32) - ASM x86 ASM 370

This is a discussion on Problem Linking (win32) - ASM x86 ASM 370 ; Per another discussion here, I decided to switch to using the win32 object format via nasm -f win32, and I went with the golink linker. I was not able to find an app call alib to work with alink. However, ...

+ Reply to Thread
Page 1 of 2 1 2 LastLast
Results 1 to 10 of 18

Problem Linking (win32)

  1. Default Problem Linking (win32)

    Per another discussion here, I decided to switch to using the win32
    object format via nasm -f win32, and I went with the golink linker. I
    was not able to find an app call alib to work with alink.

    However, I am having a problem with my exe files after I link them.
    When I open the file up in ollydbg, I receive immediately a last
    error:

    ERROR_INVALID_HANDLE (00000006)

    The file still runs, but I'm not sure why I am receiving the error. I
    never received this last error when I linked with alink and built obj
    (OMF) files. And I'm not really good with windows as I have mainly
    stuck to writing code with gcc or gas with the gdb debugger on a BSD
    box.

    Here is the asm I am assembling with nasm and linking with golink. I
    have included the commands I am providing. I am hoping to get through
    this stuff, so that I can jump over to how the windows api handles
    files and networking. I'd like to write atomic read and write
    functions in assembly.

    ;assemble
    ;nasm -f win32 win32_func.asm
    ;golink /entry _start win32_func.obj kernel32.dll user32.dll
    msvcrt.dll

    extern MessageBoxA
    extern ExitProcess
    extern sprintf

    section .code code CLASS=CODE

    global _start
    _start:

    push ebp
    mov ebp, esp
    cld ;clear direction flag for string instructions

    push dword 0x05
    push dword 0x08
    call AddFunc
    add esp, 8
    mov dword [results], eax ; save the results

    ;create 64 byte buffer on the stack and zero out
    sub esp, 64
    mov dword edi, esp

    xor eax, eax
    mov dword ecx, 64
    rep stosb
    sub edi, 64 ; set pointer to beginning of buffer
    ; verified edi changes per the Intel Developers
    Manual
    and ollydbg

    ; sprintf(buffer, "%d", [results])

    push dword [results]
    push dword format
    push dword edi
    call [sprintf]
    add esp, 12 ; 3 dwords (4 bytes) = 12

    push byte 0
    push dword Title
    push dword edi
    push byte 0
    call [MessageBoxA]

    push dword 0
    call [ExitProcess]

    ; add two numbers together
    AddFunc:
    push ebp
    mov ebp, esp
    mov eax, [ebp+8]
    add eax, [ebp+12]
    leave
    ret

    section .date data CLASS=DATA

    Title db "Results", 0
    format db "%d", 0

    section .bss bss CLASS=BSS

    results: resd 1


  2. Default Re: Problem Linking (win32)

    On Jul 22, 1:44 pm, "bwai...@yahoo.com" <spamt...@crayne.org> wrote:
    > Per another discussion here, I decided to switch to using the win32
    > object format via nasm -f win32, and I went with the golink linker. I
    > was not able to find an app call alib to work with alink.
    >
    > However, I am having a problem with my exe files after I link them.
    > When I open the file up in ollydbg, I receive immediately a last
    > error:
    >
    > ERROR_INVALID_HANDLE (00000006)
    >


    I have isolated the problem to the C function. Do I need to do
    anything special
    when calling a C function in win32 that takes variable characters
    outside of clearing
    the stack after the function returns? And why is an error generated
    prior to executing
    my code? How does sprintf know how many parameters to process?

    I have verified the error above by making a GetLastError call before
    clearing the direction flag.

    Thanks.


  3. Default Re: Problem Linking (win32)

    bwaichu@yahoo.com wrote:
    > Per another discussion here, I decided to switch to using the win32
    > object format via nasm -f win32, and I went with the golink linker. I
    > was not able to find an app call alib to work with alink.


    http://alink.sourceforge.net/download.html

    But GoLink may be a better choice (never used it).

    ....
    > ;assemble
    > ;nasm -f win32 win32_func.asm
    > ;golink /entry _start win32_func.obj kernel32.dll user32.dll
    > msvcrt.dll
    >
    > extern MessageBoxA
    > extern ExitProcess
    > extern sprintf
    >
    > section .code code CLASS=CODE


    "-f win32" knows "section .text", "section .data", "section .bss", and
    "section .rdata", and knows the proper attributes. Probably have less
    trouble if you use 'em.

    ....
    > call [sprintf]


    Pretty sure you don't want the "[]" here.

    No idea if either of those will fix the "invalid handle" problem.
    "Courage", Brian!

    Best,
    Frank


  4. Default Re: Problem Linking (win32)

    bwaichu wrote:
    : But GoLink may be a better choice (never used it).
    :
    : <snip>...</snip>
    :
    : section .code code CLASS=CODE
    :
    : <snip>...</snip>
    :

    GoLink, PoLink, LINK all should work. It just takes a little time
    to figure out how to get things going, and then reading the proper
    things in order to figure out NASM's macro system, etc helps. More
    on this in a moment.

    "Frank Kotler" posted:
    : "-f win32" knows "section .text", "section .data", "section .bss",
    : and "section .rdata", and knows the proper attributes. Probably
    : have less trouble if you use 'em.

    Thanks for posting that, Frank. That helps, as I noticed that the
    nasm32.inc encodes the following which demonstrates that you're
    correct (I did not see Brian using an %include for that file):

    <file name="nasm32.inc">

    %imacro .CODE 0
    [section .text]
    %endmacro


    %imacro .TEXT 0
    [section .text]
    %endmacro

    ; ...snip...

    %imacro IMPORT 1
    %ifndef __imp_%1 %1
    extern %1
    %define __imp_%1 %1
    %endif
    %endmacro

    </file>

    The IMPORT directive is kind of nice. I'm not sure where the
    nasm32.inc file comes from, but it sure helps understand some
    things that have bugged me for a long while, and I can then
    implement the things needed so as to make a working file.

    Not sure why the bracketed notation occurs, or why it ends up
    preferred, so if someone has a comment on that, that would be nice.

    Something that would be really nice, would be to see the macro
    expansions in another file. NASM is a single pass compiler?
    Perhaps a two-pass? Any discussions going on? The reason I ponder
    this, is because I thought the LISTING file would show the macro
    expansions. At least that's the way I read it from documentation.

    Get the source. Know the source. Use the SOURCE, Duke.

    Yes, master... A marriage? Must I say, "I do"?
    Ok, "I do..."

    The line, "%imacro .TEXT 0", seems to use 0 as the *(all)
    contextual symbol so that ALL after the .TEXT statement gets
    dropped? How does one create a "%imacro .TEXT *" macro?

    I'm not sure I'm reading the docs right. And without two compiles,
    one producing a listing of what really gets compiled, I'm left
    wondering what's going on. In this way, I again request multiple
    passes through the source if it does not already occur. And I also
    request a proper LISTING file. Am I wrong?

    Here's the code (test.asm) and the test.lst files:

    <file name="test.asm">
    ;COMPILE
    ; NASM version 2.03.01 compiled on Jun 16 2008
    ;(1) nasm.exe -f win32 win32_func.asm
    ;(2) nasm.exe -l test.lst -f win32 test.asm
    ;
    ;LINK
    ;golink.exe /entry _start win32_func.obj kernel32.dll user32.dll msvcrt.dll
    ;golink.exe /entry _start test.obj kernel32.dll user32.dll msvcrt.dll
    ;
    ;NOTE: The PSDK library uses @16 and @4.
    ; PellesC library includes msvcrt.lib.
    ;
    ;SET LIB=Q:\SDK\Lib;Q:\Pelles\C\Lib\Win
    ;
    ;polink.exe /SUBSYSTEM:WINDOWS /entry:_start test.obj kernel32.lib user32.lib msvcrt.lib
    ;

    %define MessageBoxA _MessageBoxA@16
    %define ExitProcess _ExitProcess@4
    %define sprintf _sprintf

    extern MessageBoxA
    extern ExitProcess
    extern sprintf

    section .code CLASS=CODE
    ;section .text CLASS=CODE

    global _start
    _start:
    push ebp
    mov ebp, esp
    cld ;clear direction flag for string instructions

    push dword 0x05
    push dword 0x08
    call AddFunc
    add esp, 8
    mov dword [results], eax ; save the results

    ;create 64 byte buffer on the stack and zero out
    sub esp, 64
    mov dword edi, esp

    xor eax, eax
    mov dword ecx, 64
    rep stosb
    sub edi, 64 ; set pointer to beginning of buffer
    ; verified edi changes per the Intel Developers Manual and ollydbg

    ; sprintf(buffer, "%d", [results])

    push dword [results]
    push dword format
    push dword edi
    ;call [sprintf]
    call sprintf
    add esp, 12 ; 3 dwords (4 bytes) = 12

    push byte 0
    push dword Title
    push dword edi
    push byte 0
    ;call [MessageBoxA]
    call MessageBoxA

    push dword 0
    ;call [ExitProcess]
    call ExitProcess

    ; add two numbers together
    AddFunc:
    push ebp
    mov ebp, esp
    mov eax, [ebp+8]
    add eax, [ebp+12]
    leave
    ret

    section .data CLASS=DATA
    Title db "Results", 0
    format db "%d", 0

    section .bss CLASS=BSS
    results: resd 1
    </file>

    <file "test.lst">
    1 ;COMPILE
    2 ;nasm.exe -f win32 win32_func.asm
    3 ;nasm.exe -l test.lst -f win32 test.asm
    4 ;
    5 ;LINK
    6 ;golink.exe /entry _start win32_func.obj kernel32.dll user32.dll msvcrt.dll
    7 ;golink.exe /entry _start test.obj kernel32.dll user32.dll msvcrt.dll
    8 ;
    9 ;NOTE: The PSDK library uses @16 and @4.
    10 ; PellesC library includes msvcrt.lib.
    11 ;
    12 ;SET LIB=Q:\SDK\Lib;Q:\Pelles\C\Lib\Win
    13 ;
    14 ;polink.exe /SUBSYSTEM:WINDOWS /entry:_start test.obj kernel32.lib user32.lib msvcrt.lib
    15 ;
    16
    17 %define MessageBoxA _MessageBoxA@16
    18 %define ExitProcess _ExitProcess@4
    19 %define sprintf _sprintf
    20
    21 extern MessageBoxA
    22 extern ExitProcess
    23 extern sprintf
    24
    25 section .code CLASS=CODE
    26 ;section .text CLASS=CODE
    27
    28 global _start
    29 _start:
    30 00000000 55 push ebp
    31 00000001 89E5 mov ebp, esp
    32 00000003 FC cld ;clear direction flag for string instructions
    33
    34 00000004 6805000000 push dword 0x05
    35 00000009 6808000000 push dword 0x08
    36 0000000E E852000000 call AddFunc
    37 00000013 81C408000000 add esp, 8
    38 00000019 A3[00000000] mov dword [results], eax ; save the results
    39
    40 ;create 64 byte buffer on the stack and zero out
    41 0000001E 81EC40000000 sub esp, 64
    42 00000024 89E7 mov dword edi, esp
    43
    44 00000026 31C0 xor eax, eax
    45 00000028 B940000000 mov dword ecx, 64
    46 0000002D F3AA rep stosb
    47 0000002F 81EF40000000 sub edi, 64 ; set pointer to beginning of buffer
    48 ; verified edi changes per the Intel Developers Manual and ollydbg
    49
    50 ; sprintf(buffer, "%d", [results])
    51
    52 00000035 FF35[00000000] push dword [results]
    53 0000003B 68[08000000] push dword format
    54 00000040 57 push dword edi
    55 ;call [sprintf]
    56 00000041 E8(00000000) call sprintf
    57 00000046 81C40C000000 add esp, 12 ; 3 dwords (4 bytes) = 12
    58
    59 0000004C 6A00 push byte 0
    60 0000004E 68[00000000] push dword Title
    61 00000053 57 push dword edi
    62 00000054 6A00 push byte 0
    63 ;call [MessageBoxA]
    64 00000056 E8(00000000) call MessageBoxA
    65
    66 0000005B 6800000000 push dword 0
    67 ;call [ExitProcess]
    68 00000060 E8(00000000) call ExitProcess
    69
    70 ; add two numbers together
    71 AddFunc:
    72 00000065 55 push ebp
    73 00000066 89E5 mov ebp, esp
    74 00000068 8B4508 mov eax, [ebp+8]
    75 0000006B 03450C add eax, [ebp+12]
    76 0000006E C9 leave
    77 0000006F C3 ret
    78
    79 section .data CLASS=DATA
    80 00000000 526573756C747300 Title db "Results", 0
    81 00000008 256400 format db "%d", 0
    82
    83 section .bss CLASS=BSS
    84 00000000 <res 00000004> results: resd 1

    </file>

    The problems, I see, even though the file compiles file, links fine and
    the resulting exutable runs fine, is that the listing does not show the
    macro expansion of ".CODE", nor any of the other macro expansions. Is this
    a problem/bug?

    --
    JC
    Natural Cure For Pink-Eye (Conjunctivitis)
    http://www.associatedcontent.com/art...nctivitis.html


  5. Default Re: Problem Linking (win32)

    On Jul 23, 9:15 am, "Jim Carlock" <spamt...@crayne.org> wrote:

    >
    > Thanks for posting that, Frank. That helps, as I noticed that the
    > nasm32.inc encodes the following which demonstrates that you're
    > correct (I did not see Brian using an %include for that file):


    I am not including any macros in my file. I'm using the latest
    version
    of nasm and the latest version of golink. I want to feel out NASM
    some
    more before I start to use macros. I'm just following the NASM manual
    for the sections for win32 coff.

    A consistent error occurs upon the loading of my asm. No error occurs
    at loading if I leave out functions that link back to msvcrt.dll. I'm
    not sure if this is a linking problem or a loading problem or
    something else.
    I do know that I do not have this problem when building with alink
    and
    OMF files.

    Here's another example. This example results in this error being set
    upon loading:

    ERROR_ENVVAR_NOT_FOUND (000000CB)

    And this happens every time. Check out the value of eax after
    GetLastError is called. This could just be an issue with MS's loader
    on xp.

    ;nasm -f win32 atext.asm
    ;golink /console atext.obj kernel32.dll user32.dll msvcrt.dll

    extern printf
    extern ExitProcess
    extern GetLastError

    section .text text CLASS=TEXT

    global start
    start:

    call [GetLastError]

    push dword sText
    call printf
    add esp, 4

    push dword 0
    call [ExitProcess]

    section .data data CLASS=DATA

    sText dd "Test", 0

    Any ideas? Can you reproduce my error on your machines?



  6. Default Re: Problem Linking (win32)

    "bwaichu" asked:
    : I am not including any macros in my file. I'm using the latest
    : version of nasm and the latest version of golink. I want to feel
    : out NASM some more before I start to use macros. I'm just
    : following the NASM manual for the sections for win32 coff.

    Ok, I compiled what you provided to see what was going on myself.
    I know I've had some linking problems in the past. I link against
    the .lib files. I'm not sure that I can link against .dll files,
    but I'm willing to try.

    I use the LIB e.v. to identify the path where the .lib files are
    located. I didn't see msvcrt.lib in the Platform SDK files, so I
    had to find another location for it. And I found that in / with
    Pelles C compiler. Once I located the msvcrt.lib file, the rest
    of the problems involved making sure a _ gets placed onto the
    API declarations. Thus you see the following in the code I posted:

    %define MessageBoxA _MessageBoxA@16
    %define ExitProcess _ExitProcess@4
    %define sprintf _sprintf

    extern MessageBoxA
    extern ExitProcess
    extern sprintf

    I wanted to test out Frank's suggestion about the .CODE
    and .TEXT so while compiling I happened to remember some
    things about the win32.inc file. I knew that file held
    some important information in it because I've seen others
    use it and I've mimicked what was in it. So while trying
    to figure out the .CODE / .TEXT thing, I thought I hit on
    a possible bug. And maybe I did, I don't know, I just did
    not get what I expected to get.

    The %imacro lines expanded, but the %define lines did not
    show up in the listing file (test.lst).

    (1) You need to make sure the API get an underscore placed
    in front of them in some way I think.
    (2) I think you need to link against the .lib files, but I
    haven't gone that route and tested that. That's how I got
    your application to compile, link and run. It presented a
    small messagebox with the number 16 in it. I really did
    not get into the code so I don't even know what was to get
    placed into the MessageBox. I just wanted to compile it
    and see if I could get it to run. Shame on me.

    : A consistent error occurs upon the loading of my asm. No error
    : occurs at loading if I leave out functions that link back to
    : msvcrt.dll. I'm not sure if this is a linking problem or a
    : loading problem or something else.
    :
    : I do know that I do not have this problem when building with
    : alink and OMF files.

    Yeah, I've seen something like that in recent past about 4 months
    ago. I'll have to let someone else comment on that though.

    There are some issues with compiling to the -f win32. I played
    with that a few months ago trying to get dumpbin.exe (comes with
    MS VC6 aka MS VC98) to show the imports and exports properly and
    I ran into some issues. Unfortunately I didn't document it in a
    public place, but I think it's on my laptop (packed away at the
    moment). I did get dumpbin.exe /IMPORTS to work. I learned that
    dumpbin.exe actually calls LINK.EXE (or perhaps vice versa) to
    present the requested information.

    LINK0098.EXE /DUMP /?

    That's the VC6 (aka VC98) linker. It presents the following:

    Microsoft (R) COFF Binary File Dumper Version 5.12.8181
    Copyright (C) Microsoft Corp 1992-1998. All rights reserved.

    usage: DUMPBIN [options] [files]

    options:

    /ALL
    /ARCH
    /ARCHIVEMEMBERS
    /DEPENDENTS
    /DIRECTIVES
    /DISASM
    /EXPORTS
    /FPO
    /HEADERS
    /IMPORTS
    /LINENUMBERS
    /LINKERMEMBER[:{1|2}]
    /LOADCONFIG
    /OUT:filename
    /PDATA
    /RAWDATA[:{NONE|BYTES|SHORTS|LONGS}[,#]]
    /RELOCATIONS
    /SECTION:name
    /SUMMARY
    /SYMBOLS

    The /IMPORTS and /EXPORTS are the two switches that help with
    win32 files.

    : Here's another example. This example results in this error
    : being set upon loading:
    :
    : ERROR_ENVVAR_NOT_FOUND (000000CB)
    :
    : And this happens every time. Check out the value of eax after
    : GetLastError is called. This could just be an issue with MS's
    : loader on xp.
    :
    <code file="atext.asm">
    ;nasm -f win32 atext.asm
    ;golink /console atext.obj kernel32.dll user32.dll msvcrt.dll

    extern printf
    extern ExitProcess
    extern GetLastError

    section .text text CLASS=TEXT

    global start
    start:

    call [GetLastError]

    push dword sText
    call printf
    add esp, 4

    push dword 0
    call [ExitProcess]

    section .data data CLASS=DATA

    sText dd "Test", 0
    </code>
    :
    : Any ideas? Can you reproduce my error on your machines?
    :

    Did you get the other file to compile and run? I'll take a
    look at this later in the evening. I've got some other things
    to work out right at the moment.

    --
    JC
    Roses For The Guiness Book Of World Records?
    http://www.associatedcontent.com/art...rsburg_fl.html



  7. Default Re: Problem Linking (win32)

    On Jul 23, 3:20 pm, "Jim Carlock" <spamt...@crayne.org> wrote:

    > Did you get the other file to compile and run? I'll take a
    > look at this later in the evening. I've got some other things
    > to work out right at the moment.


    I have no problems assembling and linking these asm programs. I
    did figure out the @commandfile piece, which helps a lot. What
    I do not understand is why an error value is set upon loading
    the PE file. This happens to me when I link to msvcrt.dll.
    Otherwise, if I stick to only windows api functions, the error
    value is set to zero upon loading the PE file.

    The PE exe files run fine since the error is all ready set before
    the code executes.

    Is the setting of the error value a bug with the linker, a bug
    with the creation of the obj file, a bug with the ms loader,
    or something else? Should I clear the error value whenever
    I assemble a file that links back to msvcrt.dll after a prologue?

    Given that win32 PE files based on win32 coff have been out
    for a while, I expect someone to have run into this problem
    before. Since I do not know what is causing the error, I
    feel like my code is executing under an unknown condition.

    The closest BSD problem I ran into was the need for a prologue
    if I am using floating point instructions on amd64.

    Thanks.




  8. Default Re: Problem Linking (win32)

    You might have better results if you start with a simple solution and
    then add complexity in incremental steps. For instance:

    ,--
    | hey.asm
    ,--

    ; nasm -f win32 -o hey.obj hey.asm
    ; gcc -o hey.exe hey.obj

    section .data

    format db 10, 'Result = %d', 10, 0

    section .text

    global _main
    extern _printf

    _main:
    push 0x05
    push 0x08
    call AddFunc
    push eax
    push format
    call _printf
    add esp, 8

    xor eax, eax
    ret

    AddFunc:
    mov eax, [esp+4]
    add eax, [esp+8]
    ret 8
    `--

    Nathan.


  9. Default Re: Problem Linking (win32)

    But if your aim is to explore the Win API, then keep 'golink' but
    steer clear of any C library.

    ----8<----

    ; nasm -f win32 -o go.obj go.asm
    ; golink /console go.obj kernel32.dll

    section .bss

    wrtn: resd 1

    section .text

    global start
    extern ExitProcess
    extern GetStdHandle
    extern WriteFile

    start:

    push ebp
    mov ebp, esp
    sub esp, 4
    mov al, 13
    mov [ebp-4], al
    mov al, 0x048
    mov [ebp-3], al
    mov al, 0x049
    mov [ebp-2], al
    mov al, 13
    mov [ebp-1], al

    push -11
    call GetStdHandle

    mov ebx, esp

    push dword 0
    push wrtn
    push dword 4
    push ebx
    push eax
    call WriteFile

    push eax
    call ExitProcess

    ---->8----

    That will print "HI" to the console.

    Nathan.


  10. Default Re: Problem Linking (win32)

    Jim Carlock wrote:

    [snip]
    > "Frank Kotler" posted:
    > : "-f win32" knows "section .text", "section .data", "section .bss",
    > : and "section .rdata", and knows the proper attributes. Probably
    > : have less trouble if you use 'em.
    >
    > Thanks for posting that, Frank. That helps, as I noticed that the
    > nasm32.inc encodes the following which demonstrates that you're
    > correct (I did not see Brian using an %include for that file):
    >
    > <file name="nasm32.inc">
    >
    > %imacro .CODE 0
    > [section .text]
    > %endmacro
    >
    >
    > %imacro .TEXT 0
    > [section .text]
    > %endmacro
    >
    > ; ...snip...
    >
    > %imacro IMPORT 1
    > %ifndef __imp_%1 %1
    > extern %1
    > %define __imp_%1 %1
    > %endif
    > %endmacro
    >
    > </file>
    >
    > The IMPORT directive is kind of nice.


    Yes, but it's available only in "-f obj" output format. The above macro
    doesn't do the same thing (I don't think). AFAICS, it only prevents
    multiple "extern"s of the same function from being generated (some
    assemblers seem to do this anyway).

    > I'm not sure where the
    > nasm32.inc file comes from,


    The NasmX project, back when it was called "Nasm32", had a file by that
    name. The version I've got has similar macros, but not the same.

    > but it sure helps understand some
    > things that have bugged me for a long while, and I can then
    > implement the things needed so as to make a working file.
    >
    > Not sure why the bracketed notation occurs, or why it ends up
    > preferred, so if someone has a comment on that, that would be nice.


    Well, there's "call imm", and "call [mem]". If the latter is going to
    work - say "call [sprintf]" - *somewhere* has to exist:

    sprintf dd address_of_real_sprintf

    Since it isn't in *our* code, the linker must create it... or not. I've
    *only* seen this work using "-f obj" and Alink, but I think it's more a
    question of "which linker" than "which output format". Brian appears to
    be using it with GoLink, but there's some question if his code is
    "really" working right.

    (Or did you mean the brackets around "[section .text]"? That's the "raw"
    form, which doesn't set the "__SECT__" standard macro. Possibly
    intentional, in this case - usually you want the "user" form "section
    ..text", which does set "__SECT__".)

    > Something that would be really nice, would be to see the macro
    > expansions in another file. NASM is a single pass compiler?
    > Perhaps a two-pass?


    Two pass, by default. You can get more with the "-O" switch, but "-O999"
    specifies the *maximum* number of passes to use. It quits when jump
    displacements are resolved.

    > Any discussions going on?


    Sure:

    <http://sourceforge.net/mailarchive/forum.php?forum_name=nasm-devel>

    Not about number of passes, though...

    > The reason I ponder
    > this, is because I thought the LISTING file would show the macro
    > expansions. At least that's the way I read it from documentation.


    It does show the macro expansion (unless declared ".nolist"). My source
    says "diz 1, 2", the list file says:


    28 diz 1, 2
    29 <1>
    30 <1> %ifdef USEAX
    31 <1> mov eax, %1
    32 <1> %else
    33 0000000A BB02000000 <1> mov ebx, %2
    34 <1> %endif
    35 <1>
    36

    If you want to see it with the parameters evaluated (besides in the
    code, as above) use the "-e" switch (preprocess only).

    > Get the source. Know the source. Use the SOURCE, Duke.
    >
    > Yes, master... A marriage? Must I say, "I do"?
    > Ok, "I do..."


    Aren't you supposed to say "speak now or forever hold your peace" before
    that?

    > The line, "%imacro .TEXT 0", seems to use 0 as the *(all)
    > contextual symbol so that ALL after the .TEXT statement gets
    > dropped?


    No, "%imacro .TEXT 0" defines a macro - case insensitive - that takes no
    parameters. If there's anything after ".TEXT", it isn't this macro, so
    the preprocessor passes it along unchanged.

    > How does one create a "%imacro .TEXT *" macro?


    %imacro .TEXT 0-*
    [section .text %1]
    %endmacro

    The "-*" indicates a "greedy" parameter - everything after the zeroth
    (everything, IOW) is "lumped together" as "%1". I think that's what you
    have in mind. The "-" shouldn't be read as a minus sign, in this case -
    "%macro foo 1-3" means one through three parameters, not -1. "foo" with
    no, or more than 3, parameters won't match.

    > I'm not sure I'm reading the docs right. And without two compiles,
    > one producing a listing of what really gets compiled, I'm left
    > wondering what's going on.


    That's why I prefer to disassemble the executable - see what it *really*
    looks like after the linker's had its way with it.

    > In this way, I again request multiple
    > passes through the source if it does not already occur. And I also
    > request a proper LISTING file. Am I wrong?


    Add the "-O" switch... if you think more than two passes is going to
    help. It does with forward references (sometimes), but I don't think
    it'll make any difference here.

    > Here's the code (test.asm) and the test.lst files:
    >
    > <file name="test.asm">
    > ;COMPILE
    > ; NASM version 2.03.01 compiled on Jun 16 2008
    > ;(1) nasm.exe -f win32 win32_func.asm
    > ;(2) nasm.exe -l test.lst -f win32 test.asm
    > ;
    > ;LINK
    > ;golink.exe /entry _start win32_func.obj kernel32.dll user32.dll msvcrt.dll
    > ;golink.exe /entry _start test.obj kernel32.dll user32.dll msvcrt.dll
    > ;
    > ;NOTE: The PSDK library uses @16 and @4.
    > ; PellesC library includes msvcrt.lib.
    > ;
    > ;SET LIB=Q:\SDK\Lib;Q:\Pelles\C\Lib\Win
    > ;
    > ;polink.exe /SUBSYSTEM:WINDOWS /entry:_start test.obj kernel32.lib user32.lib msvcrt.lib
    > ;
    >
    > %define MessageBoxA _MessageBoxA@16
    > %define ExitProcess _ExitProcess@4
    > %define sprintf _sprintf
    >
    > extern MessageBoxA
    > extern ExitProcess
    > extern sprintf
    >
    > section .code CLASS=CODE
    > ;section .text CLASS=CODE
    >
    > global _start
    > _start:
    > push ebp
    > mov ebp, esp
    > cld ;clear direction flag for string instructions
    >
    > push dword 0x05
    > push dword 0x08
    > call AddFunc
    > add esp, 8
    > mov dword [results], eax ; save the results
    >
    > ;create 64 byte buffer on the stack and zero out
    > sub esp, 64
    > mov dword edi, esp
    >
    > xor eax, eax
    > mov dword ecx, 64
    > rep stosb
    > sub edi, 64 ; set pointer to beginning of buffer
    > ; verified edi changes per the Intel Developers Manual and ollydbg
    >
    > ; sprintf(buffer, "%d", [results])
    >
    > push dword [results]
    > push dword format
    > push dword edi
    > ;call [sprintf]
    > call sprintf
    > add esp, 12 ; 3 dwords (4 bytes) = 12
    >
    > push byte 0
    > push dword Title
    > push dword edi
    > push byte 0
    > ;call [MessageBoxA]
    > call MessageBoxA
    >
    > push dword 0
    > ;call [ExitProcess]
    > call ExitProcess
    >
    > ; add two numbers together
    > AddFunc:
    > push ebp
    > mov ebp, esp
    > mov eax, [ebp+8]
    > add eax, [ebp+12]
    > leave
    > ret
    >
    > section .data CLASS=DATA
    > Title db "Results", 0
    > format db "%d", 0
    >
    > section .bss CLASS=BSS
    > results: resd 1
    > </file>
    >
    > <file "test.lst">
    > 1 ;COMPILE
    > 2 ;nasm.exe -f win32 win32_func.asm
    > 3 ;nasm.exe -l test.lst -f win32 test.asm
    > 4 ;
    > 5 ;LINK
    > 6 ;golink.exe /entry _start win32_func.obj kernel32.dll user32.dll msvcrt.dll
    > 7 ;golink.exe /entry _start test.obj kernel32.dll user32.dll msvcrt.dll
    > 8 ;
    > 9 ;NOTE: The PSDK library uses @16 and @4.
    > 10 ; PellesC library includes msvcrt.lib.
    > 11 ;
    > 12 ;SET LIB=Q:\SDK\Lib;Q:\Pelles\C\Lib\Win
    > 13 ;
    > 14 ;polink.exe /SUBSYSTEM:WINDOWS /entry:_start test.obj kernel32.lib user32.lib msvcrt.lib
    > 15 ;
    > 16
    > 17 %define MessageBoxA _MessageBoxA@16
    > 18 %define ExitProcess _ExitProcess@4
    > 19 %define sprintf _sprintf
    > 20
    > 21 extern MessageBoxA
    > 22 extern ExitProcess
    > 23 extern sprintf
    > 24
    > 25 section .code CLASS=CODE
    > 26 ;section .text CLASS=CODE
    > 27
    > 28 global _start
    > 29 _start:
    > 30 00000000 55 push ebp
    > 31 00000001 89E5 mov ebp, esp
    > 32 00000003 FC cld ;clear direction flag for string instructions
    > 33
    > 34 00000004 6805000000 push dword 0x05
    > 35 00000009 6808000000 push dword 0x08
    > 36 0000000E E852000000 call AddFunc
    > 37 00000013 81C408000000 add esp, 8
    > 38 00000019 A3[00000000] mov dword [results], eax ; save the results
    > 39
    > 40 ;create 64 byte buffer on the stack and zero out
    > 41 0000001E 81EC40000000 sub esp, 64
    > 42 00000024 89E7 mov dword edi, esp
    > 43
    > 44 00000026 31C0 xor eax, eax
    > 45 00000028 B940000000 mov dword ecx, 64
    > 46 0000002D F3AA rep stosb
    > 47 0000002F 81EF40000000 sub edi, 64 ; set pointer to beginning of buffer
    > 48 ; verified edi changes per the Intel Developers Manual and ollydbg
    > 49
    > 50 ; sprintf(buffer, "%d", [results])
    > 51
    > 52 00000035 FF35[00000000] push dword [results]
    > 53 0000003B 68[08000000] push dword format
    > 54 00000040 57 push dword edi
    > 55 ;call [sprintf]
    > 56 00000041 E8(00000000) call sprintf
    > 57 00000046 81C40C000000 add esp, 12 ; 3 dwords (4 bytes) = 12
    > 58
    > 59 0000004C 6A00 push byte 0
    > 60 0000004E 68[00000000] push dword Title
    > 61 00000053 57 push dword edi
    > 62 00000054 6A00 push byte 0
    > 63 ;call [MessageBoxA]
    > 64 00000056 E8(00000000) call MessageBoxA
    > 65
    > 66 0000005B 6800000000 push dword 0
    > 67 ;call [ExitProcess]
    > 68 00000060 E8(00000000) call ExitProcess
    > 69
    > 70 ; add two numbers together
    > 71 AddFunc:
    > 72 00000065 55 push ebp
    > 73 00000066 89E5 mov ebp, esp
    > 74 00000068 8B4508 mov eax, [ebp+8]
    > 75 0000006B 03450C add eax, [ebp+12]
    > 76 0000006E C9 leave
    > 77 0000006F C3 ret
    > 78
    > 79 section .data CLASS=DATA
    > 80 00000000 526573756C747300 Title db "Results", 0
    > 81 00000008 256400 format db "%d", 0
    > 82
    > 83 section .bss CLASS=BSS
    > 84 00000000 <res 00000004> results: resd 1
    >
    > </file>
    >
    > The problems, I see, even though the file compiles file, links fine and
    > the resulting exutable runs fine, is that the listing does not show the
    > macro expansion of ".CODE", nor any of the other macro expansions. Is this
    > a problem/bug?


    You haven't included any macro for ".CODE" that I can see. If it
    specified no parameters, it still wouldn't expand ('cause its not "your"
    macro!).

    Try the "-e" switch and see if it gives you anything more helpful. You
    *will* have to do it twice - "-e" is "preprocess only", but it'll show
    you the code as fed to the assembler. (outputs to stdout unless there's
    an output file specified with "-o")

    Personally, I find listing files almost completely useless. The
    "addresses" aren't runtime addresses but mere file offsets, half the
    "code" is left to be filled in by the linker (might be useful for
    debugging Nasm, but if I cared what the opcode was I'd do it "Wolfgang
    style"), and the "source code"... well, I *knew* that. What's to like?

    Best,
    Frank


+ Reply to Thread
Page 1 of 2 1 2 LastLast