From: James Daughtry on 4 Feb 2006 18:06 I'm not sure if this is as good a place as comp.lang.asm.x86, so I'll go ahead and post and see what happens. :-) I've recently started learning assembly language. After a brief flirtation with HLA, FASM, and RosASM (in that order), I find myself working with NASM and I'm enjoying myself thoroughly. However, being an active tutor with higher level languages, I'm aware that just because something works doesn't mean it's the best way, or even correct at all. ;-) So I'm a little paranoid about learning bad habits while I teach myself assembly through the sparse tutorials and assembler documentation that I come across. Anyway, here's my latest work that took several hours (one of actual work, the rest just tweaking)... The scary part is that I could write the same thing in C in a matter of minutes. ;-) I would be most appreciative if I could get your opinions on how I'm doing so far and what I can do to improve. %macro invoke 2 push %2 call %1 add esp,4 %endmacro section .data prompt: db 'Type a short message: ',0 result: db 'The message in binary is: ',0 section .bss msg: resb 1024 i: resd 1 section .text global _main extern _gets, _printf, _putchar _main: pusha invoke _printf,prompt invoke _gets,msg invoke _printf,result ; Process every character in the string mov ebx,0 jmp begin_walk continue_walk: mov dword [i],8 ; Process a single character convert: rol byte [msg + ebx],1 ; Print msb to lsb invoke lsbtoc,dword [msg + ebx] invoke _putchar,eax dec dword [i] cmp dword [i],0 jne convert ; end convert invoke _putchar,32 inc ebx begin_walk: cmp byte [msg + ebx],0 jne continue_walk ; end continue_walk popa mov eax,0 ret ; end main ; Convert the lsb to '0' or '1' lsbtoc: mov eax,[esp + 4] and eax,1 not eax not eax add eax,48 ret Yes, I know gets is dangerous, but I couldn't figure out how to supply stdin to fgets... Thank you very much for your time and patience. :-)
From: Herbert Kleebauer on 5 Feb 2006 13:50 James Daughtry wrote: > > I'm not sure if this is as good a place as comp.lang.asm.x86, so I'll > go ahead and post and see what happens. :-) Any place is better than a censored place. > I've recently started learning assembly language. After a brief > flirtation with HLA, FASM, and RosASM (in that order), I find myself > working with NASM and I'm enjoying myself thoroughly. And how about GAS? It's syntax is far superior to any "Intel" assembler. > However, being an > active tutor with higher level languages, I'm aware that just because > something works doesn't mean it's the best way, or even correct at all. > ;-) So I'm a little paranoid about learning bad habits while I teach > myself assembly through the sparse tutorials and assembler > documentation that I come across. Then compare your solution with the one generated by the C compiler (with and without optimization). > Anyway, here's my latest work that took several hours (one of actual > work, the rest just tweaking)... The scary part is that I could write > the same thing in C in a matter of minutes. ;-) I would be most > appreciative if I could get your opinions on how I'm doing so far and > what I can do to improve. > i: resd 1 > _main: > ; Process every character in the string > mov ebx,0 > jmp begin_walk > > continue_walk: > mov dword [i],8 Why not use one of the free registers instead of a memory variable? > ; Process a single character > convert: > rol byte [msg + ebx],1 ; Print msb to lsb Don't know, but I think it is faster to copy the byte into a register and rotate within the register than rotate a memory location. > > invoke lsbtoc,dword [msg + ebx] Why the overhead for a subroutine call? "lsbtoc" is only used in one place, so better use inline code. > invoke _putchar,eax > > dec dword [i] > cmp dword [i],0 This "cmp" instruction does nothing, "dec" already set the zero flag. > jne convert > ; end convert > ; Convert the lsb to '0' or '1' > lsbtoc: > mov eax,[esp + 4] > and eax,1 > not eax > not eax "not eax" twice? Here how I would do it: 00000100: 66 be 0000013b move.l #text,r5 00000106: 66 e8 00000002 bsr.l convert 0000010c: eb 53 br.b exit convert: 0000010e: 66 4e dec.l r5 00000110: eb 17 br.b _10 00000112: b0 00 _30: move.b #0,r0 00000114: d1 c0 _20: rol.w #1,r0 00000116: 04 30 add.b #'0',r0 00000118: 66 e8 00000029 bsr.l printch 0000011e: 67 e2 f1 dbf.l r2,_30 00000121: b0 20 move.b #' ',r0 00000123: 66 e8 0000001e bsr.l printch 00000129: 66 31 c0 _10: eor.l r0,r0 0000012c: 66 b9 00000008 move.l #8,r2 00000132: 66 46 inc.l r5 00000134: 67 02 26 add.b (r5),m0 00000137: 75 db bne.b _20 00000139: 66 c3 rts.l 0000013b: 68 65 6c 6c 6f 20 00000141: 77 6f 72 6c 64 00 text: dc.b "hello world",0 ; DOS version for printch and exit: ; replace with an appropriate version for WINDOWS/LINUX 00000147: 66 60 printch:movem.l r0-r7,-(sp) 00000149: 67 66 8d 94 24 0000014e: 0000001c lea.l 7*4(r7){s7},r1 00000152: b4 40 move.b #$40,m0 00000154: b9 0001 move.w #1,r2 00000157: 31 db eor.w r3,r3 00000159: cd 21 trap #$21 0000015b: 66 61 90 movem.l (sp)+,r0-r7 0000015e: 66 c3 rts.l 00000160: c3 exit: rts.w
From: ?a/b on 5 Feb 2006 16:15 On 4 Feb 2006 15:06:19 -0800, "James Daughtry" <mordock32(a)hotmail.com> wrote: >I'm not sure if this is as good a place as comp.lang.asm.x86, so I'll >go ahead and post and see what happens. :-) > >I've recently started learning assembly language. After a brief >flirtation with HLA, FASM, and RosASM (in that order), I find myself >working with NASM and I'm enjoying myself thoroughly. However, being an >active tutor with higher level languages, I'm aware that just because >something works doesn't mean it's the best way, or even correct at all. >;-) So I'm a little paranoid about learning bad habits while I teach >myself assembly through the sparse tutorials and assembler >documentation that I come across. > >Anyway, here's my latest work that took several hours (one of actual >work, the rest just tweaking)... The scary part is that I could write >the same thing in C in a matter of minutes. ;-) I would be most >appreciative if I could get your opinions on how I'm doing so far and >what I can do to improve. [] > ret > >Yes, I know gets is dangerous, but I couldn't figure out how to supply >stdin to fgets... easy, you write in a c file for your favorite c compiler "fgets(array, 256, stdin);" and you say to compiler that you want the assembly file out then you see in the assembly file the name the compiler traslate "stdin"; than use that name >Thank you very much for your time and patience. :-) this is my version if i well understand the problem (with nasm and borland compiler) ; nasmw -f obj this_file.asm ; bcc32 this_file.obj section _DATA public align=4 class=DATA use32 Scrivi db "Scrivi > " , 0 Errore db "Errore" , 10 , 0 Errore1 db "Errore" , 0 Errore_linea_troppo_lunga db "Errore linea troppo lunga" , 0 Errore_contenuto_linea db "Errore contenuto linea" , 10 , 0 La_tua_stringa_in_binario_eI_ db "La tua stringa in binario e': [" , 0 chiudi db "]" , 10 , 0 val db 0 extern _printf , _fgets , __streams , _putchar global _main section _TEXT public align=1 class=CODE use32 ; void print_bin(char* org) ; stampa l'argomento nello standard output ; in forma di stringa binaria ; s=0j, 4i, 8b, 12ra, 16org print_bin: push ebx push esi push edi %define @org esp+16 push La_tua_stringa_in_binario_eI_ call _printf add esp, 4 mov esi, [@org] ..a0: mov ebx, 0 mov bl, [esi] cmp ebx, 0 je .fn mov edi, 8 ..a1: mov eax, '0' test ebx, 128 jz .a2 mov eax, '1' ..a2: push eax call _putchar add esp, 4 shl ebx, 1 dec edi jnz .a1 inc esi jmp short .a0 ..fn: push chiudi call _printf add esp, 4 %undef @org pop edi pop esi pop ebx ret ; k= 0k, 4Ra, 8(a)argc, 12(a)argv _main: ; foo[256], sp[4], w[4] push ebp ; 11..266, 267..270, 271..274<512 mov ebp, esp sub esp, 512 push ebx push esi push edi %define @argc ebp+8 %define @argv ebp+12 %define @foo ebp-266 %define @w ebp-274 mov eax, 0 mov ebx, ebp ..l0: mov byte[ebx], 0 inc eax dec ebx cmp eax, 400 jb .l0 ..a0: ; qui sotto __streams==stdin push Scrivi call _printf add esp, 4 lea eax, [@foo] push __streams push 256 push eax call _fgets add esp, 12 cmp eax, 0 jne .l4 ..l1: push Errore call _printf add esp, 4 jmp .fine ..l2: push Errore_linea_troppo_lunga call _printf add esp, 4 jmp .fine ..l3: push Errore_contenuto_linea call _printf add esp, 4 jmp .fine ..l4: cmp byte[eax+254], 0 jne .l2 push eax call print_bin add esp, 4 ..fine: mov eax, 0 %undef @argc %undef @argv %undef @foo %undef @w pop edi pop esi pop ebx mov esp, ebp pop ebp ret
From: James Daughtry on 5 Feb 2006 17:22 > This rises the question, why you want to do assembly programming. To learn. Any benefits from knowing assembly are simply side effects. > If you want to understand low level programming then this doesn't > only mean to know the CPU instruction set but also the native OS API. Only a fool has a strong opinion about something he doesn't understand. ;-) I'm familiar enough with the Win32 API; I choose not to use it in my spare time, and my work doesn't require it, so I've no need for it working with assembly. > An assembler like RosAsm is only useful for writing applications > in assembler (for learning assembly programming you better do > anything by hand). I'll keep that in mind, thanks.
From: o///annabee on 5 Feb 2006 17:40
P? Sun, 05 Feb 2006 21:55:21 +0100, skrev Herbert Kleebauer <klee(a)unibwm.de>: > James Daughtry wrote: > > But because it doesn't make any sense to write > an application in assembler, RosAsm is useful for ...? I agree with many things you say Herbert, but the above sentance is really untrue. Have you tried writing something with RosAsm? It is not only that RosAsm, of course, is the best tool for learning assembly. But it is evidently also the best tool for doing Windows programming. You _cannot_ see this without trying. Its impossible to find all the goodies of RosAsm when not using it over time. RosAsm doesnt have any other shortcommings, then the ones it was never designed for. For windows programming it is simply the very best tool yet available. |