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

.



Relevant Pages

  • Re: Problem Linking (win32)
    ... push dword 0x05 ... mov dword, eax; save the results ... mov dword edi, esp ...
    (comp.lang.asm.x86)
  • Re: Problem Linking (win32)
    ... Something that would be really nice, would be to see the macro ... push dword 0x05 ... mov dword, eax; save the results ... mov dword edi, esp ...
    (comp.lang.asm.x86)
  • Problem Linking (win32)
    ... push dword 0x05 ... mov dword, eax; save the results ... mov dword edi, esp ...
    (comp.lang.asm.x86)
  • Problem with Function Call with NASM
    ... extern MessageBoxA ... push dword 0x05 ... mov dword edi, esp ... mov dword ecx, 64 ...
    (comp.lang.asm.x86)
  • Re: misc, OT: C compiler, x86-64 or not x86-64...
    ... or partly branch my lower compiler and make an x86-64 version as well?... ... push ebp; mov ebp, esp ... push dword HhDMmIPiboWKIGVIFi ... lea eax, ...
    (alt.lang.asm)