flat assembler
Message board for the users of flat assembler.
Index
> Linux > Print argc + argv to stdout sample program |
Author |
|
revolution 27 Feb 2015, 10:20
Looks good.
But what happens when you have more than 9 arguments? |
|||
27 Feb 2015, 10:20 |
|
alkap 27 Feb 2015, 11:16
Thanks for replying.
Outputting a string representation of argc when its value is greater than 9 calls for a better int2str routine, doesn't it? I'll go away and work on this one. Thanks for the pointer. |
|||
27 Feb 2015, 11:16 |
|
HaHaAnonymous 27 Feb 2015, 16:13
[ Post removed by author. ]
Last edited by HaHaAnonymous on 28 Feb 2015, 17:38; edited 2 times in total |
|||
27 Feb 2015, 16:13 |
|
alkap 27 Feb 2015, 17:03
Wow! Thanks for your input.
It's all fairly new to me. So, I'll need some time to digest what's been said. Everyone's input is much appreciated though. |
|||
27 Feb 2015, 17:03 |
|
alkap 28 Feb 2015, 16:46
I've come up with a program to test itoa, which seems to work as intended:
Code: ; itoa -- convert integers to strings. ; fasm itoa.fasm itoa format ELF executable 3 entry start segment readable executable start: push 824 push buf call itoa push buf call print push nl call print exit: xor ebx, ebx mov eax, 1 int 80h itoa: push ebp mov ebp, esp xor ecx, ecx ; string buffer index mov eax, [ebp+0Ch] ; dividend mov ebx, 0Ah ; divisor mov esi, [ebp+8] ; string buffer L1: cdq div ebx ; eax = edx:eax/ebx add edx, '0' ; convert int to ascii mov byte [esi+ecx*1], dl inc ecx test eax, eax jz L2 jmp L1 L2: dec ecx xor edx, edx L3: cmp ecx, edx jb L4 mov al, byte [esi+edx*1] xchg al, byte [esi+ecx*1] mov byte [esi+edx*1], al inc edx dec ecx jmp L3 L4: inc edx mov byte [esi+edx*1], 0 mov esp, ebp pop ebp ret 4*2 strlen: push ebp mov ebp, esp push edi sub ecx, ecx mov edi, [ebp+8] not ecx sub al, al cld repne scasb not ecx pop edi lea eax, [ecx-1] mov esp, ebp pop ebp ret 4 print: push ebp mov ebp, esp mov eax, [ebp+8] push eax call strlen mov edx, eax mov eax, WRITE mov ebx, STDOUT mov ecx, [ebp+8] int 80h mov esp, ebp pop ebp ret 4 segment readable writable buf rb 0Bh nl db 0Ah, 0 WRITE = 4 STDOUT = 1 But when I try to use itoa in my cmdargs program, I get a segmentation fault, when accessing the itoa parameters. My guess is, my passing the value of argc to itoa is wrong. I've spent some time trying to figure out what's wrong, but so far to no avail. I would appreciate some hints please. Thanks. Code: ; cmdargs -- display argc, and argv ; fasm cmdargs.fasm cmdargs format ELF executable 3 entry start segment readable executable start: push argcstr call print pop eax ; convert argc to string representation push eax push buf call itoa push buf call print push nl call print pop ecx ; get rid of argc argv: pop ecx ; pop off stack argvn test ecx, ecx jz exit push ecx call print push nl call print jmp argv exit: mov eax, 1 xor ebx, ebx int 80h itoa: push ebp mov ebp, esp xor ecx, ecx ; string buffer index mov eax, [ebp+0Ch] ; dividend mov ebx, 0Ah ; divisor mov esi, [ebp+8] ; string buffer L1: cdq div ebx ; eax = edx:eax/ebx add edx, '0' ; convert int to ascii mov byte [esi+ecx*1], dl ; [base+index*scale] inc ecx test eax, eax jz L2 jmp L1 L2: dec ecx xor edx, edx L3: cmp ecx, edx jb L4 mov al, byte [esi+edx*1] xchg al, byte [esi+ecx*1] mov byte [esi+edx*1], al inc edx dec ecx jmp L3 L4: inc edx mov byte [esi+edx*1], 0 mov esp, ebp pop ebp ret 4*2 strlen: push ebp mov ebp, esp xor eax, eax mov ecx, -1 cld mov edi, [ebp+8] repnz scasb mov eax, edi sub eax, [ebp+8] sub eax, 1 mov esp, ebp pop ebp ret 4 print: push ebp mov ebp, esp mov eax, [ebp+8] push eax call strlen mov edx, eax mov eax, WRITE mov ebx, STDOUT mov ecx, [ebp+8] int 80h mov esp, ebp pop ebp ret 4 segment readable writeable argcstr db 'argc: ', 0 nl db 0Ah, 0 buf rb 0Bh WRITE = 4 STDOUT = 1 |
|||
28 Feb 2015, 16:46 |
|
revolution 28 Feb 2015, 16:52
It appears as though you forgot to remove this line when you converted to stdcall format:
Code: pop ecx ; get rid of argc |
|||
28 Feb 2015, 16:52 |
|
alkap 28 Feb 2015, 17:07
Thanks. But that doesn't seem to be it.
I've removed the line you referred to, recompiled the program, and still getting a segfault: Code: ./cmdargs argv1 argv2 argv3 argv4 argv5 argv6 argv7 argv8 argc: Segmentation fault |
|||
28 Feb 2015, 17:07 |
|
HaHaAnonymous 11 Mar 2015, 01:17
alkap
Your code is crashing in itoa (and probably more ahead), it does not return. I would check that. |
|||
11 Mar 2015, 01:17 |
|
alkap 11 Mar 2015, 08:14
Thanks. I've been trying to figure out where I went wrong for a little while now.
I too gathered that the problem was either in my manipulating the stack prior to calling itoa, or in itoa itself. Although the itoa test program seems to work alright. As far as I understand how itoa is supposed to work is, it doesn't return any value, but it manipulates the buffer via a pointer, esi. I've also been looking into the way display_digit was implemented in the fasm source code for some insightful ideas. I'll keep at it, and report back when succeeded. |
|||
11 Mar 2015, 08:14 |
|
revolution 11 Mar 2015, 08:39
There are a couple of problems with your string reversing code.
1) For a length of one character you have ecx=0 which causes the loop to execute over the entire memory. 2) for longer strings you truncate it in the middle of the number. I suggest you test your itoa with numbers of varying lengths from 1 to 10 digits to root out all the bugs. |
|||
11 Mar 2015, 08:39 |
|
alkap 11 Mar 2015, 09:10
Thanks for the pointers.
I'll report back on the progress made. |
|||
11 Mar 2015, 09:10 |
|
alkap 12 Mar 2015, 21:11
Version of itoa inspired by code found in Programming Ground Up, chapter 10, section Converting Numbers for Display.
Code: ; cmdargs -- display argc, and argv ; fasm cmdargs.fasm cmdargs format ELF executable 3 entry start segment readable executable start: push argcstr call print pop ecx ; convert argc to string representation push ecx push buf call itoa push buf call print push nl call print argv: pop ecx ; pop off stack argvn test ecx, ecx jz exit push ecx call print push nl call print jmp argv exit: mov eax, 1 xor ebx, ebx int 80h itoa: push ebp mov ebp, esp xor ecx, ecx ; string buffer index mov eax, [ebp+0Ch] ; dividend mov edi, 0Ah ; divisor conversion_loop: xor edx, edx div edi ; eax = edx:eax/ebx add edx, '0' ; convert int to ascii push edx inc ecx test eax, eax jz end_conversion_loop jmp conversion_loop end_conversion_loop: mov edx, [ebp+8] ; string buffer copy_reversing_loop: pop eax mov byte [edx], al dec ecx inc edx test ecx, ecx jz end_copy_reversing_loop jmp copy_reversing_loop end_copy_reversing_loop: mov byte [edx], 0 mov esp, ebp pop ebp ret 4*2 strlen: push ebp mov ebp, esp push edi sub ecx, ecx mov edi, [ebp+8] not ecx sub al, al cld repne scasb not ecx pop edi lea eax, [ecx-1] mov esp, ebp pop ebp ret 4 print: push ebp mov ebp, esp mov eax, [ebp+8] push eax call strlen mov edx, eax mov eax, WRITE mov ebx, STDOUT mov ecx, [ebp+8] int 80h mov esp, ebp pop ebp ret 4 segment readable writeable argcstr db 'argc: ', 0 nl db 0Ah, 0 buf rb 0Bh WRITE = 4 STDOUT = 1 Sample run: Code: ./cmdargs argv1 argv2 argv3 argv4 argv5 argv6 argv7 argv8 argv9 argv10 argv11 argv12 argc: 13 ./cmdargs argv1 argv2 argv3 argv4 argv5 argv6 argv7 argv8 argv9 argv10 argv11 argv12 |
|||
12 Mar 2015, 21:11 |
|
HaHaAnonymous 13 Mar 2015, 05:04
alkap
I'm glad you fixed it! Quote:
Aligning the start of every "function" and "data" (preferably at 16, or at least a multiple of 2) seems to be beneficial. You can use the "align" directive for that. Not that it would bring something catastrophically good, it is just a hint. I am not the right person for that but seeing unaligned code and data drives me crazy. D: I apologize for any inconveniences (if any). |
|||
13 Mar 2015, 05:04 |
|
alkap 13 Mar 2015, 06:26
HaHaAnonymous
Thanks for your feedback. So for the 'data' segment the align directive would go straight after the segment definition, as shown below, wouldn't it? Code: fasm/source/Linux/fasm.asm:257,259 segment readable writeable align 4 What about functions? Does the align directive go straight after the function label, or would it suffice to declare it globally like so? Code: segment readable executable align 10h start: Thanks. |
|||
13 Mar 2015, 06:26 |
|
HaHaAnonymous 13 Mar 2015, 06:33
You just need to put it above the label or data definition (or anything else):
Code: align 16 function: mov eax,eax ret align 4 data: db '0231231' align 4 db '05564' align 4 dd ? Last edited by HaHaAnonymous on 05 Apr 2015, 01:48; edited 1 time in total |
|||
13 Mar 2015, 06:33 |
|
alkap 13 Mar 2015, 06:58
Understood. Thanks.
|
|||
13 Mar 2015, 06:58 |
|
alkap 15 Mar 2015, 19:01
I thought I'd try implementing cmdargs with function parameters passed via registers. Once again, I'd appreciate this forum's members' feedback on this piece of code. I looked to fasm's source code for ideas.
Code: ; cmdargs_regs -- test passing function parameter passing via registers. ; fasm cmdargs_regs.fasm cmdargs_regs format ELF executable 3 entry start segment readable executable start: mov esi, argcstr call print pop edx ; edx = argc mov esi, buf call itoa ; void itoa(int, char*) mov esi, buf call print ; void print(char*) mov esi, nl call print argv: pop edx ; pop off stack argv test edx, edx jz exit mov esi, edx call print mov esi, nl call print jmp argv exit: movzx ebx,al mov eax, EXIT int 80h align 16 itoa: ; void itoa(int, char*); eax = dividend ; esi = char* mov eax, edx ; eax = dividend xor ecx, ecx ; string buffer index mov ebx, 0Ah ; divisor conversion_loop: xor edx, edx div ebx ; eax = edx:eax/ebx add edx, '0' ; convert int to ascii push edx inc ecx test eax, eax jz end_conversion_loop jmp conversion_loop end_conversion_loop: mov edx, esi ; string buffer copy_reversing_loop: pop eax mov byte [edx], al dec ecx inc edx test ecx, ecx jz end_copy_reversing_loop jmp copy_reversing_loop end_copy_reversing_loop: mov byte [edx], 0 ret align 16 strlen: ; int strlen(char*); esi == char*; eax == strlen mov edi, esi or ecx, -1 xor al, al repne scasb neg ecx sub ecx, 2 xchg eax, ecx ret align 16 print: ; int print(char*); esi = char* call strlen mov edx, eax mov eax, WRITE mov ebx, STDOUT mov ecx, esi int 80h ; TODO: check for write error ret segment readable writeable align 4 argcstr db 'argc: ',0 nl db 0Ah,0 buf rb 0Bh WRITE = 4 EXIT = 1 STDOUT = 1 Sample output: Code: ./cmdargs_regs argv^(1 2 3 4 5 6 7 8 9 10) argc: 11 ./cmdargs_regs argv1 argv2 argv3 argv4 argv5 argv6 argv7 argv8 argv9 argv10 |
|||
15 Mar 2015, 19:01 |
|
HaHaAnonymous 15 Mar 2015, 20:24
Quote:
The align directive aligns only the data that comes after it... Then further alignment is needed (if you desire) for the others if your data size was not enough to align. Code: align 4 data0: db '7 bytes' ; the data below is not aligned, it starts at offset 7 data1: db 'not aligned' In my opinion, it would be nice if you "separate" the initialized data (often read-only) from the data that is retrieved at run-time by another means and here are some of my ideas of code organizations most people hate: Code: format ELF executable 3 entry function segment readable executable align 16 function: ; as you can see, it is able to fit the longest instruction "name" without causing trouble to your code mov eax,eax movd eax,xmm0 vaeskeygenassist xmm1,xmm2,8 movdqa xmm0, dqword [data01] ret align 16 function2: ; as you can see, it is able to fit the longest instruction "name" without causing trouble to your code mov eax,eax sub eax,eax pop eax vaeskeygenassist xmm1,xmm2,8 jmp eax segment readable ; read only data align 4 data0: db 'Woof, woof!' align 4 data1: db 'Fatal Error! D:' ; for strange reasons, also align file size 16 bytes, or whatever your prefer :D align 16 ; add more 16 bytes to realize alignment dq 2 dup($00) segment readable writeable ; read write uninitialized data, buffers, etc... align 4 buf1: rb 1024 align 4 buf2: rq 8 align 4 data00: rb 256 align 16 data01: rq 16 align 16 data02: dq ? Or you can put your data above your executable section, or whatever order you wish! Last edited by HaHaAnonymous on 22 Mar 2015, 02:11; edited 6 times in total |
|||
15 Mar 2015, 20:24 |
|
alkap 15 Mar 2015, 20:29
I see. Thanks.
|
|||
15 Mar 2015, 20:29 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.