From: James Daughtry on
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
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
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
> 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
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.