NASM - The Netwide Assembler
NASM Forum => Summer of Code Ideas => Topic started by: uncle Richard on May 07, 2019, 07:42:06 AM
-
Not so long ago, Nasm (version 0.98.38 compiled on Mar 5 2011) could not correctly count near jumps. Now, uninitialized variables still stink, too. Here is a simple program:
//no.c (c) Tereshkov_OE
//sites.google.com/site/excelmidi
extern void printf (const char *_Format,...);
int LookAtMe, AtMeToo, AtMeTwo;
int num[50];
void _start(void)
{
LookAtMe=67; AtMeToo=45; AtMeTwo=29;
LookAtMe = LookAtMe+AtMeToo+AtMeTwo;
printf(" %d\n", LookAtMe);
}
Take Pelles C 8.0 and get:
[global _start]
[section .text]
_start:
push ebp
mov ebp,esp
sub esp,4
mov dword [(LookAtMe)],67
mov dword [(AtMeToo)],45
mov dword [(AtMeTwo)],29
mov eax,dword [(LookAtMe)]
add eax,dword [(AtMeToo)]
mov dword [ebp+(-4)],eax ;stupidity
add eax,dword [(AtMeTwo)]
mov dword [(LookAtMe)],eax
push dword [(LookAtMe)]
push dword (@10)
call printf
add esp,(8+3)&(~3) ;double stupidity
mov esp,ebp
pop ebp
ret
[section .bss]
[common num 200]
[common AtMeTwo 4]
[common AtMeToo 4]
[common LookAtMe 4]
[extern printf]
[section .rdata]
@10:
db ' %d',10,0
[cpu pentium]
Nasm (version 2.14.02 compiled on Dec 26 2018) like compiler. Tcc as linker. Run the program. Result 87. From which it follows that nobody uses Nasm under Windows32, including the authors. PureBasic 3.20 was try to use Nasm and then went to Fasm. Why?
The same program for PCC&Yasm like compiler and TCC as linker brings 141. Archive: https://sites.google.com/site/excelmidi/file-sto/nasm.zip
-
Three days have passed. But H. Peter Anvin, Cyrill Gorcunov, Chang Seok Bae, Jim Kukunas, Frank B. Kotler are silent. So. The main problem with Nasm is that it does not have a linker. And if it is not needed in Linux, in Windows it is absolutely necessary. TCC is a C compiler and a satisfactory linker for the elf format, simultaneously. But no one can guarantee on how correct this TCC is.
A bunch of Gcc+Yasm+TCC brings a result of 87, too. Thus, Gcc and TCC can be defective, and Nasm can be normal. The earlier Nasm will acquire its own linker and IDE, the better. Fasm popularity is the best proof of this.
It should be only one regret. MSVC, GCC, TCC, DmC, Pelle C, PCC, NASM, FASM, YASM, GOASM, UASM, MASM are excellent compilers, each in its own way. And this is good. The bad thing is that they are completely incompatible with each other. Even at the 'Hello World' level. And they will not.
Pelle C is closest to me. I wrote a small converter Pelle -> NASM + TCC. Everything works, except comm variables. Even Agner Fog does not know what to do with them.
-
Hi uncle Richard,
Welcome to the forum.
I am terribly sorry you had trouble with Nasm.
Best,
Frank
-
A year has passed. All the sages, who wanted or could have, already spoken out. It's time to put dot in the end. Let's look inside the finished program.
Section .text
* Entry Point:
00401000: 55 push ebp
00401001: 89E5 mov ebp, esp
00401003: 81EC04000000 sub esp, 00000004
00401009: C7054C20400043000000 mov dword ptr [0040204C], 00000043
00401013: C7054C2040002D000000 mov dword ptr [0040204C], 0000002D
0040101D: C7054C2040001D000000 mov dword ptr [0040204C], 0000001D
00401027: A14C204000 mov eax, [0040204C]
0040102C: 03054C204000 add eax, [0040204C]
00401032: 8945FC mov [ebp-04], eax
00401035: 03054C204000 add eax, [0040204C]
0040103B: A34C204000 mov [0040204C], eax
00401040: FF354C204000 push dword ptr [0040204C]
00401046: 6800304000 push 00403000
0040104B: E810000000 call msvcrt.printf
00401050: 81C408000000 add esp, 00000008
00401056: 89EC mov esp, ebp
00401058: 5D pop ebp
00401059: C3 ret
Maybe this is all insidious TCC? Take a look at the object file.
public _start
comm num:byte:0c8h
comm AtMeTwo:byte:04h
comm AtMeToo:byte:04h
comm LookAtMe:byte:04h
extrn printf
.text segment
_start:
push EBP
mov EBP,ESP
sub ESP,4
mov dword ptr @SYM32[00h],043h
mov dword ptr @SYM32[00h],02Dh
mov dword ptr @SYM32[00h],01Dh
mov EAX,@SYM32[00h]
add EAX,@SYM32[00h]
mov -4[EBP],EAX
add EAX,@SYM32[00h]
mov @SYM32[00h],EAX
push dword ptr @SYM32[00h]
push offset FLAT:@10[047h]@SYM32
call printf@PC32
add ESP,8
mov ESP,EBP
pop EBP
ret
.text ends
.bss segment
.bss ends
end
No, not TCC. This is NASM/YASM such. TCC is a great linker and compiler. But, as it turned out, it had nothing to link except itself. Of course, one can make assumptions about the role of "mov dword [ebp + (- 4)], eax", which is completely unnecessary and which PelleC so shamelessly generates. But the fact remains that only very brave and reckless programmers, like you, can use NASM/YASM. :) And who just came up with these not initialized global variables?! Agner Fog will confirm.
-
Day two. The weather was great. The princess was bad. :) As often happens in such cases, the solution to the problem turned out to be very simple:
[section .bss]
[common num 200:4]
[common AtMeTwo 4:4]
[common AtMeToo 4:4]
[common LookAtMe 4:4]
[extern printf]
[section .rdata]
@10:
db ' %d',10,0
Those who play AT&T with Yasm:
.comm LookAtMe,04,4
.comm AtMeToo,04,4
.comm AtMeTwo,04,4
.comm num,0310,4
Why int num[50]; >>> .comm num,0310,4 in pcc 1.1.0 for win32? Who Knows?:)
pcc is not only :) GCC:
.comm LookAtMe,16
.comm AtMeToo,16
.comm AtMeTwo,16
.comm num,208
The Nasm object file looks exactly the same, but now it works:
public _start
comm num:byte:0c8h
comm AtMeTwo:byte:04h
comm AtMeToo:byte:04h
comm LookAtMe:byte:04h
extrn printf
.text segment
_start:
push EBP
mov EBP,ESP
sub ESP,4
mov dword ptr @SYM32[00h],043h
mov dword ptr @SYM32[00h],02Dh
mov dword ptr @SYM32[00h],01Dh
mov EAX,@SYM32[00h]
add EAX,@SYM32[00h]
add EAX,@SYM32[00h]
mov @SYM32[00h],EAX
push dword ptr @SYM32[00h]
push offset FLAT:@10[041h]@SYM32
call printf@PC32
add ESP,8
mov ESP,EBP
pop EBP
ret
.text ends
.bss segment
.bss ends
end
Understand why - don't even try! :) Anyway, try TCC as linker for Nasm. It's easy. Welcome Universal Student IDE https://sites.google.com/site/excelmidi/universal_student_ide/universal_student_ide_en (https://sites.google.com/site/excelmidi/universal_student_ide/universal_student_ide_en) for all compilers.
-
Looking at the endless abundance of high-level languages, one might think that assembler has long died. But this is not so. Suppose you write a library and want to collect all the strings in one object file. Even using the lowest level of all the higher levels - C, nothing will work. All C compilers are the same in this respect. I have an answer why this is happening. But for now, I will refrain from discussing.
The simplest program and assembler for it.
#define STR1 ";string_1\r\n"
#define STR2 ";string_2\r\n"
#define STR3 ";string_3\r\n"
#define STR4 ";string_4\r\n"
#define STR5 ";string_5\r\n"
#define STR6 ";string_6\r\n"
extern int printf();
void _start (void){
printf(STR1);
printf(STR2);
printf(STR5);
}
section code
[global _start]
_start:
; Line 8: void _start (void){
L_4:
; Line 9: printf(STR1);
push dword L_1
call printf
pop ecx
; Line 10: printf(STR2);
push dword L_2
call printf
pop ecx
; Line 11: printf(STR5);
push dword L_3
call printf
pop ecx
; Line 12: }
L_5:
ret
section data
section code
section data
section string
L_3:
db ";string_5"
db 0dh
db 0ah
db 00h
L_2:
db ";string_2"
db 0dh
db 0ah
db 00h
L_1:
db ";string_1"
db 0dh
db 0ah
db 00h
section const
section code
[extern printf]
We have 6 strings, and only 3 are in the object file. Let's cut the program down to the can’t.
#define STR1 ";string_1\r\n"
#define STR2 ";string_2\r\n"
#define STR3 ";string_3\r\n"
#define STR4 ";string_4\r\n"
#define STR5 ";string_5\r\n"
#define STR6 ";string_6\r\n"
section code
section data
section code
section data
section const
The object file is full zero. And now we take the assembler and by the hands, hands :)
SECTION .data
SECTION .data
STR1:
db ";string_1", 0dh, 0ah, 00h
STR2:
db ";string_2", 0dh, 0ah, 00h
STR3:
db ";string_3", 0dh, 0ah, 00h
STR4:
db ";string_4", 0dh, 0ah, 00h
STR5:
db ";string_5", 0dh, 0ah, 00h
STR6:
db ";string_6", 0dh, 0ah, 00h
;.....
-
Life goes on. And it is no secret that Nasm is still quite stupid enough. Now no dll from Nasm/Yasm elf output. Example.
//num_count_1.c
#define EOF (-1)
extern printf();
extern getchar();
_export void bb(void){
int nc;
for(nc=0;getchar()!=EOF;++nc);
printf("%d\n", nc); }
_export int __dllstart(){bb();
return 0;}
++++++++++++++++++++++++++++++++++++++
nasm -f elf num_count_1.asm
SECTION .text
SECTION .data
SECTION .bss
SECTION .text
[BITS 32]
[GLOBAL bb]
bb:
;
; Line 7: _export void bb(void){
;
PUSH EBP
MOV EBP,ESP
SUB ESP,BYTE 08H
L_3:
MOV DWORD [EBP-04H],00H
JMP SHORT L_6
L_4:
;
; Line 9: for(nc=0;getchar()!=EOF;++nc);
;
L_5:
INC DWORD [EBP-04H]
L_6:
CALL getchar
CMP EAX,BYTE 0FFFFFFFFH
JNE SHORT L_4
L_7:
;
; Line 10: printf("%d\n", nc); }
;
PUSH DWORD [EBP-04H]
PUSH DWORD L_1
CALL printf
ADD ESP,BYTE 08H
L_2:
MOV ESP,EBP
POP EBP
RET
[GLOBAL __dllstart]
__dllstart:
;
; Line 11: _export int __dllstart(){bb();
;
PUSH EBP
MOV EBP,ESP
L_9:
CALL bb
;
; Line 12: return 0;}
;
MOV EAX,00H
L_8:
POP EBP
RET
SECTION .data
L_1:
DB 025H,064H,0AH,00H
SECTION .text
[BITS 32]
SECTION .text
[BITS 32]
export __dllstart ; parser error
export bb ; parser error
[EXTERN getchar]
[EXTERN printf]
Got parser error & parser error. Maybe elf format have no exports in Windows? Have! Tcc prove it well. Let me guess. Frank Kotler again will say - I am terribly sorry you had trouble with Nasm. O, thank you Frank.:) Longing is green. Black dog. Dumps.
-
Day two. The weather was bad. The princess was wet. I love wet princesses very much. And you? :) Here is a small dump from the previous listing. newdll.o
00000000 7F 45 4C 46 01 01 01 00-00 00 00 00 00 00 00 00 .ELF............
00000010 01 00 03 00 01 00 00 00-00 00 00 00 00 00 00 00 ................
00000020 40 00 00 00 00 00 00 00-34 00 00 00 00 00 28 00 @.......4.....(.
00000030 08 00 04 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
00000040 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
00000050 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
00000060 00 00 00 00 00 00 00 00-01 00 00 00 01 00 00 00 ................
00000070 06 00 00 00 00 00 00 00-80 01 00 00 1C 00 00 00 ................
00000080 00 00 00 00 00 00 00 00-10 00 00 00 00 00 00 00 ................
00000090 07 00 00 00 01 00 00 00-03 00 00 00 00 00 00 00 ................
000000A0 A0 01 00 00 09 00 00 00-00 00 00 00 00 00 00 00 ................
000000B0 04 00 00 00 00 00 00 00-0D 00 00 00 08 00 00 00 ................
000000C0 03 00 00 00 00 00 00 00-B0 01 00 00 04 00 00 00 ................
000000D0 00 00 00 00 00 00 00 00-04 00 00 00 00 00 00 00 ................
000000E0 12 00 00 00 03 00 00 00-00 00 00 00 00 00 00 00 ................
000000F0 B0 01 00 00 36 00 00 00-00 00 00 00 00 00 00 00 ....6...........
00000100 01 00 00 00 00 00 00 00-1C 00 00 00 02 00 00 00 ................
00000110 00 00 00 00 00 00 00 00-F0 01 00 00 B0 00 00 00 ................
00000120 06 00 00 00 08 00 00 00-04 00 00 00 10 00 00 00 ................
00000130 24 00 00 00 03 00 00 00-00 00 00 00 00 00 00 00 $...............
00000140 A0 02 00 00 51 00 00 00-00 00 00 00 00 00 00 00 ....Q...........
00000150 01 00 00 00 00 00 00 00-2C 00 00 00 09 00 00 00 ........,.......
00000160 00 00 00 00 00 00 00 00-00 03 00 00 18 00 00 00 ................
00000170 05 00 00 00 01 00 00 00-04 00 00 00 08 00 00 00 ................
00000180 55 89 E5 6A 40 68 00 00-00 00 FF 35 00 00 00 00 U..j@h.....5....
00000190 6A 00 E8 FC FF FF FF 83-C4 10 5D C3 00 00 00 00 j.........].....
000001A0 46 72 6F 6D 20 44 4C 4C-00 00 00 00 00 00 00 00 From DLL........
000001B0 00 2E 74 65 78 74 00 2E-64 61 74 61 00 2E 62 73 ..text..data..bs
000001C0 73 00 2E 73 68 73 74 72-74 61 62 00 2E 73 79 6D s..shstrtab..sym
000001D0 74 61 62 00 2E 73 74 72-74 61 62 00 2E 72 65 6C tab..strtab..rel
000001E0 2E 74 65 78 74 00 00 00-00 00 00 00 00 00 00 00 .text...........
000001F0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
00000200 01 00 00 00 00 00 00 00-00 00 00 00 04 00 F1 FF ................
00000210 00 00 00 00 00 00 00 00-00 00 00 00 03 00 01 00 ................
00000220 00 00 00 00 00 00 00 00-00 00 00 00 03 00 02 00 ................
00000230 00 00 00 00 00 00 00 00-00 00 00 00 03 00 03 00 ................
00000240 2E 00 00 00 03 00 00 00-00 00 00 00 00 00 01 00 ................
00000250 32 00 00 00 1A 00 00 00-00 00 00 00 00 00 01 00 2...............
00000260 36 00 00 00 00 00 00 00-00 00 00 00 00 00 02 00 6...............
00000270 23 00 00 00 00 00 00 00-00 00 00 00 10 00 01 00 #...............
00000280 3A 00 00 00 00 00 00 00-00 00 00 00 10 00 03 00 :...............
00000290 45 00 00 00 00 00 00 00-00 00 00 00 10 00 00 00 E...............
000002A0 00 45 3A 5C 00 00 00 00-00 00 00 00 00 00 00 00 .E:\............
000002B0 00 00 00 00 00 00 00 5C-6E 65 77 64 6C 6C 2E 41 .......\newdll.A
000002C0 53 4D 00 68 65 6C 6C 6F-5F 66 75 6E 63 00 4C 5F SM.hello_func.L_
000002D0 33 00 4C 5F 32 00 4C 5F-31 00 68 65 6C 6C 6F 5F 3.L_2.L_1.hello_
000002E0 64 61 74 61 00 4D 65 73-73 61 67 65 42 6F 78 41 data.MessageBoxA
000002F0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
00000300 06 00 00 00 01 03 00 00-0C 00 00 00 01 04 00 00 ................
00000310 13 00 00 00 02 0A 00 00-00 00 00 00 00 00 00 00 ................
I made it by hand.:) Therefore, there may be small errors. But I tried and was extremely attentive.:) It is enough to change some bytes and Tcc will accept this file for execution to DLL. If you managed correctly, a def file should appear. newdll.def - LIBRARY newdll.dll EXPORTS hello_data hello_func Successes.:) I am terribly sorry you had trouble with me, Frank.:)