NASM - The Netwide Assembler
NASM Forum => Using NASM => Topic started by: AAG on August 25, 2010, 01:34:57 PM
-
Hi
To cut a long story short, is there a way for nasm to export the public functions in the OMF format, in the same way as the free borland c++ 5.5 command line tools?
Using Agnoer Fog's "Object file converter" (objconv http://www.agner.org/optimize/) I've dissassembles a simple C file contain 2 functions, applied the suggested "borland fixups" and compiled with nasm -fobj.
The code I'm compiling is :-
; Disassembly of file: .\bc\bcc.obj
; Fri Aug 20 22:42:17 2010
; Mode: 32 bits
; Syntax: YASM/NASM
; Instruction set: 80386
global _A
global _B
DGROUP GROUP _DATA, _BSS
SECTION _TEXT align=4 execute use32 ; section number 1, code
_A: ; Function begin
push ebp ; 0000 _ 55
mov ebp, esp ; 0001 _ 8B. EC
pop ebp ; 0003 _ 5D
ret ; 0004 _ C3
; _A End of function
_B: ; Function begin
push ebp ; 0005 _ 55
mov ebp, esp ; 0006 _ 8B. EC
pop ebp ; 0008 _ 5D
ret ; 0009 _ C3
; _B End of function
(NB The only fixup I haven't applied is that each function needs to be its own section - but please see below)
Running objconv -ds lists the following for a native borland object file :-
Public names:
_A, Segment _TEXT, Group none, Offset 0x0, Type 0
Public names:
_B, Segment _TEXT, Group none, Offset 0x5, Type 0
Running the same for the NASM object file gives :-
Public names:
_A, Segment _TEXT, Group none, Offset 0x0, Type 0
_B, Segment _TEXT, Group none, Offset 0x5, Type 0
The delphi linker (and I presume borland c linker) only appears to be able to "see" the 1st public name for a given section. Hence the reason for borland nasm tutorials saying you have to delcare each pubic function in its own section.
I had an email back from Agner Fog which said :-
"The file produced by bcc has separate sections of the _text segment, i.e.
start text
define A
end text
start text
define B
end text
I don't know if NASM can do this? MASM has an end segment directive, but NASM doesn't. "
Is there any way of being able to create the OMF as per borland c++ at with NASM at the moment? If not, would it be possible for submit a change request(?) to have some sort of extension added to the omf on the global instruction, eg global _A:borland ????
Thanks
Andy
PS: I have a large NASM file which declares around 15 public functions which works if I go for nasm -fwin32 and then use objconv on it. It would be great if NASM could produce OMF as the borland c++ 5.5 to save having to declare a load of separate sections with jumps OR change the code to insert the new code sctions + then fix the other calls to use the updated section.
-
If assembling to "-f win32" and "objconv -fomf" works for ya, that's what I would do, at least for now.
There's a "feature request tracker" at SourceForge:
http://sourceforge.net/tracker/?group_id=6208&atid=356208
I would not guarantee that it'll get you any satisfaction - there are a lot of open requests.
I've heard of this problem with Delphi, and the "put everything in its own segment" solution. It "sounds like a Borland problem, to me!" :)
Perhaps some macros could be written to "put everything in its own segment" automatically - ugly, and probably not much help with existing code...
Maybe someone can look at what "objconv" does to make it work, and "fix" Nasm to make Delphi happy... but I wouldn't hold my breath, Andy. Wish I could give you a more optimistic answer.
Best,
Frank
-
Perhaps some macros could be written to "put everything in its own segment" automatically - ugly, and probably not much help with existing code...
It's not much help at all, because you would have to name every segment different - which means that every segment would really have to be a different segment. Otherwise, NASM automatically coalesces all the labels exported from one segment in the output file.
Maybe someone can look at what "objconv" does to make it work, and "fix" Nasm to make Delphi happy...
The file produced by bcc has separate sections of the _text segment, i.e.
start text
define A
end text
start text
define B
end text
I don't know if NASM can do this? MASM has an end segment directive, but NASM doesn't.
The solution is to output "global _A:borland" (or whatever syntax you implement) in its own "segment record" of the output file (i.e. .obj), but with the same segment name. NASM currently can't be used to do that. You would have to look into outobj.c for that, around line 2086 (where the comment says "Write the PUBDEF records").
-
Sorry for the delayed reply. Told ya not to hold your breath! :)
Right, CM, that's where we'd fix it, I guess. Maybe nearer the "pub crawl :)" label, actually... Perhaps just moving that final "obj_emit(orp);" up into the "for" loop would do it(?).
But maybe outobj.c needs a lot more than that! I observe that if I assemble to "-f win32" and convert to OMF with "objconv", I get a completely different set of record types than if I assemble with "-f obj". There's an "omfdump.c" in the "misc/" directory of the nasm source (thanks to whoever put that there!). It shows that where Agner uses "PUBDEF32", "-f obj" uses "PUBDEF16"(!!!). Seems to work - except for Borland's tools - but it really doesn't look "right" to me.
Let's drag it out in the middle of the floor and let the cat sniff it. Here's my test file:
section _TEXT align=4 execute use32
global foo
foo:
ret
global bar
bar:
ret
global baz
baz:
ret
Here's what "omfdump" makes of "-f obj"...
80 THEADR 11 bytes, checksum DB (valid)
0000: 09 62 74 65 73 74 2e 61-73 6d : .btest.asm
88 COMENT 30 bytes, checksum 88 (valid)
[NP=0 NL=0 UD=00] 00 Translator
0002: 1a 54 68 65 20 4e 65 74-77 69 64 65 20 41 73 73 : .The Netwide a**
0012: 65 6d 62 6c 65 72 20 32-2e 30 39 : embler 2.09
96 LNAMES 8 bytes, checksum B9 (valid)
0000: 00 05 5f 54 45 58 54 : .._TEXT
98 SEGDEF16 7 bytes, checksum B1 (valid)
0000: a9 03 00 02 01 01 : ......
90 PUBDEF16 24 bytes, checksum 95 (valid)
0000: 00 01 03 66 6f 6f 00 00-00 03 62 61 72 01 00 00 : ...foo....bar...
0010: 03 62 61 7a 02 00 00 : .baz...
88 COMENT 4 bytes, checksum 91 (valid)
[NP=0 NL=1 UD=00] A2 Link pass separator
0002: 01 : .
a0 LEDATA16 7 bytes, checksum 0F (valid)
0000: 01 00 00 c3 c3 c3 : ......
8b MODEND32 2 bytes, checksum 73 (valid)
0000: 00 : .
And here's what it thinks of "-f obj" followed by "objconv -fomf"...
80 THEADR 12 bytes, checksum AC (valid)
0000: 0a 62 74 65 73 74 33 2e-6f 62 6a : .btest3.obj
96 LNAMES 32 bytes, checksum C2 (valid)
0000: 04 46 4c 41 54 04 43 4f-44 45 04 44 41 54 41 03 : .FLAT.CODE.DATA.
0010: 42 53 53 05 43 4f 4e 53-54 05 5f 54 45 58 54 : BSS.CONST._TEXT
99 SEGDEF32 9 bytes, checksum AA (valid)
0000: a9 03 00 00 00 06 02 00- : ........
9a GRPDEF 2 bytes, checksum 63 (valid)
0000: 01 : .
91 PUBDEF32 12 bytes, checksum 1A (valid)
0000: 01 01 03 66 6f 6f 00 00-00 00 00 : ...foo.....
91 PUBDEF32 12 bytes, checksum 28 (valid)
0000: 01 01 03 62 61 72 01 00-00 00 00 : ...bar.....
91 PUBDEF32 12 bytes, checksum 1F (valid)
0000: 01 01 03 62 61 7a 02 00-00 00 00 : ...baz.....
a1 LEDATA32 9 bytes, checksum 0C (valid)
0000: 01 00 00 00 00 c3 c3 c3- : ........
8a MODEND16 2 bytes, checksum 74 (valid)
0000: 00 : .
Note that Nasm uses MODEND32 while objconv uses MODEND16. I almost think Nasm has it right in that case... I dunno. I guess either works?
Another "symptom"... I took an old "hello world MessageBox" executable (assembled with "-f obj" and linked with... probably Alink(?)... I think it used to work...) and ran "objconv -fnasm" on it. It sees my code section as "no execute" and emits DBs instead of disassembling it. Could be a glitch in objconv, but I think it a lot more likely that it's a sign that outobj.c needs a serious re-write!
I'm not able to test any such proposed rewrite. (that's a lie - I'm not "willing"... I could run MS's stuff if I wanted to...) So unless someone is seriously interested in digging into this... Don't hold your breath...
Best,
Frank