Author Topic: Sendin register as macro argument  (Read 21858 times)

Offline dreamCoder

  • Full Member
  • **
  • Posts: 107
Sendin register as macro argument
« on: September 07, 2013, 02:34:42 AM »
Just want to know if it is even possible to do like this in NASM.

Code: [Select]
%macro viewreg 1

mov bx, %1

%endmacro

viewreg ax

Thanks


Offline dreamCoder

  • Full Member
  • **
  • Posts: 107
Re: Sendin register as macro argument
« Reply #1 on: September 07, 2013, 03:02:00 AM »
Sorry, the problem solved already.

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Sendin register as macro argument
« Reply #2 on: September 07, 2013, 04:32:03 AM »
Okay... yeah you can do that. A problem, if you call it that, is that if you do "viewreg bx" it'll generate "mov bx, bx". A little "%if" comparison will eliminate it, if you care.

Best,
Frank


Offline dreamCoder

  • Full Member
  • **
  • Posts: 107
Re: Sendin register as macro argument
« Reply #3 on: September 07, 2013, 09:41:27 PM »
Thanks for the advice Frank.

Offline dreamCoder

  • Full Member
  • **
  • Posts: 107
Re: Sendin register as macro argument
« Reply #4 on: September 08, 2013, 03:34:24 AM »
Hi again Frank. I wrote this macro to display the content of a register

Code: [Select]
%macro viewreg 1
pusha
jmp %%tab
%%htable db '0123456789ABCDEF'
%%tab:
mov bx, %%htable
mov cx, %1
mov di, 0
mov si, 0
xchg ch, cl
jmp %%main
%%main:
mov dx, cx
and dl, 0x0F0
and cl, 0x0F
shr dl, 4
mov al, dl
xlatb
call %%putc
mov al, cl
xlatb
call %%putc
inc si
cmp si, 2
    je %%quit
mov cl, dh
jmp %%main
%%putc:
push ax
mov ah, 0x0e
int 0x10
pop ax
ret
%%quit:
popa
%endmacro

Possible usage:
Code: [Select]
org 100h
%include 'mac16.mac'

segment .code

mov bx, 3
viewreg bx
call newline
viewreg sp
jmp exit

newline:
        mov ah, 0x0e
mov al, 0x0d
int 0x10
mov al, 0x0a
int 0x10
    ret

exit:
mov ah, 0
int 0x16
int 0x20

segment .data
nothing db 0

Is it possible to pass the register's name to the macro as well so that we can have a display like

BX=0003

instead of just the content?

Thanks.
 
« Last Edit: September 08, 2013, 04:00:52 AM by dreamCoder »

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Sendin register as macro argument
« Reply #5 on: September 08, 2013, 08:04:30 AM »
Well, I dunno. I thought I could do it with just a:
Code: [Select]
db "%1"
...etc. But this gives me a literal "%1" in my string instead of "bx". There may be a way to do this using "%defstr", but I haven't been able to find it (I am not a sophisticated macro user!). I have managed to do it by using two parameters, one with quotes and one without. This is UGLY!

Code: [Select]
%macro viewreg 2
[section .data]
%%regname db %1, " = ", 0
__SECT__
    pusha
    mov si, %%regname
%%topname:
    lodsb
    cmp al, 0
    jz %%endname
    call %%putc
    jmp %%topname
%%endname:
    popa

pusha
jmp %%tab
%%htable db '0123456789ABCDEF'
%%tab:
mov bx, %%htable
mov cx, %2 ; do this before altering bx?
mov di, 0
mov si, 0
xchg ch, cl
jmp %%main
%%main:
mov dx, cx
and dl, 0x0F0
and cl, 0x0F
shr dl, 4
mov al, dl
xlatb
call %%putc
mov al, cl
xlatb
call %%putc
inc si
cmp si, 2
    je %%quit
mov cl, dh
jmp %%main
%%putc:
push ax
mov ah, 0x0e
int 0x10
pop ax
ret
%%quit:
popa
%endmacro

org 100h
section .code
mov bx, 3
viewreg "bx", bx
ret

I have not tested this - not in the mood to boot up DOS. It "looks like" it's producing what I had in mind. You can probably fix my errors, if any.

A possible advantage to the "two parameter" macro is that you could do:
Code: [Select]
viewreg "frooble count", bx
if you wanted to.

Does this work with bx, as you had it? It "looks" to me like it's going to display the address of your hex table, not what was in bx originally. I think you should set up cx with %1 before you alter bx (as per comment). If it produces "mov cx, cx", that's life - won't hurt. If you use it with something other than a 16-bit register (or other appropriate operand for "mov cx, ...") you'll get errors, of course. This is going to produce a lot of "duplicate" code if you use it more than a couple of times. A subroutine (possibly called by a macro), might be more appropriate here. If you don't mind "duplicate" code, no problem.

Best,
Frank




Offline dreamCoder

  • Full Member
  • **
  • Posts: 107
Re: Sendin register as macro argument
« Reply #6 on: September 09, 2013, 07:03:51 AM »
thanks for the solution frank. I learned many nasm things from your suggestion.

As for the BX, I moved the instruction after the mov cx, %2 so that cx get the current value of BX instead of the htable Thanks for spotting the bug.

Will post the full once I got it cleaned up.

Offline Bryant Keller

  • Forum Moderator
  • Full Member
  • *****
  • Posts: 360
  • Country: us
    • About Bryant Keller
Re: Sendin register as macro argument
« Reply #7 on: October 18, 2013, 04:12:09 AM »
To make the register name a quoted string, use the %defstr directive.

Code: [Select]
%push
%defstr %$regName %1
db %$regName, 0
%pop

About Bryant Keller
bkeller@about.me

Offline dreamCoder

  • Full Member
  • **
  • Posts: 107
Re: Sendin register as macro argument
« Reply #8 on: January 02, 2014, 06:53:34 PM »
Hi Frank and Bryan.

Have been doing translation jobs for my 16-bit hobby macros in other ASM language and I intend to release it in full to NASM board especially for newbies and hobbyists alike. The problem is I can only translate half of it since my knowledge of NASM is very limited, so is my time. Most of the problem lies in the macro parameters that can be taken as tokens.

in *ASM:

Code: [Select]
macro viewreg reg,base  ;2 macro arguments
{
        ....
        if base eq bin ; bin is a token. Not a variable, constant or a string
        ...
        end if
        ...
       
}

Called like this:

Code: [Select]
...
viewreg ax,bin
...

Is there any equivalence in NASM for the %if...%endif part of the code above that evaluate tokens like bin? I need it so that I can extend my macros because for now my macros are pretty basic with only minimum features, unlike the ones I already completed in other language. If you can show me how, then maybe I can apply them to the rest of the pending macros.

This is one example of my half-completed macro. The purpose is to display the content of the register and the options to display multiple base conversions of it (this is my problem so far).

NOTE:putchar,printbin, printdec and prints are another macros

Code: [Select]
%macro viewreg 2
pusha
        mov ax,%1
        mov si,4
        mov bx,16
        xor dx,dx
%if %1 == ax
     prints "AX:"
%elif %1 == bx
     prints "BX:"
%elif %1 == cx
     prints "CX:"
%elif %1 == dx
     prints "DX:"
%elif %1 == di
     prints "DI:"
%elif %1 == si
     prints "SI:"
%elif %1 == bp
     prints "BP:"
%elif %1 == sp
     prints "SP:"
%elif %1 == cs
     prints "CS:"
%elif %1 == ds
     prints "DS:"
%elif %1 == es
     prints "ES:"
%elif %1 == ss
     prints "SS:"
%endif
%%begin:
        div bx
        push dx
        xor dx,dx
        dec si
        test si,si
        jz %%convert
        jmp %%begin
%%convert:
        inc si
        pop ax
        add al,30h
        cmp al,39h
jle %%display
        add al,7
%%display:     
        putchar al
        cmp si,4
je %%exit
        jmp %%display
%%exit:
        %if %2 == ????         ;this part
             printbin %1
        %elseif %2 == ???
             printdec %1
        %endif 
        popa
%endmacro

Thanks for your patience and time.

« Last Edit: January 02, 2014, 06:55:56 PM by dreamCoder »

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Sendin register as macro argument
« Reply #9 on: January 03, 2014, 03:37:26 PM »
Hi dreamCoder,

I think you'd want "%ifidn" for this, or "%ifidni" for case-insensitive.

http://www.nasm.us/xdoc/2.11/html/nasmdoc4.html#section-4.4.5

Code: [Select]
%ifidni %2, bin
;...
That's untested, but I think it should do what you want. (might want quotes around "bin", etc. but I don't think so)

Best,
Frank




Offline dreamCoder

  • Full Member
  • **
  • Posts: 107
Re: Sendin register as macro argument
« Reply #10 on: January 03, 2014, 07:16:24 PM »
Thanks Frank. That did solve some of the problem. My next problem is when using the %ifidn in testing multiple cases of %2 like I commented below. It doesn't affect my code. What I want to do with the test is to make sure that if any of the tokens (-o,-b,-d,-s) exist, it takes a slightly different path and should affect the other test down below (that prints their base equivalences). Is this even the correct way to use %ifidn? It however works when I used %ifnidn but the code path will produce incorrect result.

Code: [Select]
%macro reg 1-3
pusha
%ifidn %2,-o || %2,-d || %2,-b || %2,-s ;PROBLEM
push %1
%endif
mov ax,%1
mov si,4
mov bx,16
xor dx,dx
%if %1 == ax
puts "AX:",-line
%elif %1 == bx
puts "BX:",-line
%elif %1 == cx
puts "CX:",-line
%elif %1 == dx
puts "DX:",-line
%elif %1 == di
puts "DI:",-line
%elif %1 == si
puts "SI:",-line
%elif %1 == bp
puts "BP:",-line
%elif %1 == sp
puts "SP:",-line
%elif %1 == cs
puts "CS:",-line
%elif %1 == ds
puts "DS:",-line
%elif %1 == es
puts "ES:",-line
%elif %1 == ss
puts "SS:",-line
%endif
%%begin:   
div bx
        push dx
        xor dx,dx
        dec si
        test si,si
        jz %%conv
        jmp %%begin
%%conv:
inc si
        pop ax
        add al,30h
        cmp al,39h
jle %%disp
        add al,7
%%disp:   
putchar al
        cmp si,4
je %%done
        jmp %%conv
%%done:   
%ifidn %2,-b || -d || -o || -s ;PROBLEM
putchar ' '
putchar '['
pop %1
%else
jmp %%exit
%endif

%ifidn %2,-b
putbin %1,-line
%elifidn %2,-o
putoct %1,-line
%elifidn %2,-d
putint %1,,-line
%elifidn %2,-s
putint %1,-s,-line
%endif
putchar ']'
%%exit:
%ifnidn %3,-line
line
%endif
popa
%endmacro

Thanks for your responds.

Offline dreamCoder

  • Full Member
  • **
  • Posts: 107
Re: Sendin register as macro argument
« Reply #11 on: January 03, 2014, 07:31:02 PM »
The expected output is:

Code: [Select]
mov cx,35h
reg cx

Displays CX:0035

Code: [Select]
mov cx,100h
reg cx,-d ;display decimal equivalence

Displays CX:0100 [256]

Code: [Select]
mov cx,0FFh
reg cx,-b ;display binary equivalence

Displays CX:00FF [0000000011111111]


Offline Bryant Keller

  • Forum Moderator
  • Full Member
  • *****
  • Posts: 360
  • Country: us
    • About Bryant Keller
Re: Sendin register as macro argument
« Reply #12 on: January 06, 2014, 12:02:09 AM »
My next problem is when using the %ifidn in testing multiple cases of %2 like I commented below. It doesn't affect my code. What I want to do with the test is to make sure that if any of the tokens (-o,-b,-d,-s) exist, it takes a slightly different path and should affect the other test down below (that prints their base equivalences). Is this even the correct way to use %ifidn?

No, this isn't the correct way to use %ifidn. The %ifidn directive expects two parameters, not an expression. The || stuff is invalid in this case. You should use multiple %[el]ifidn statements.

Code: ("Replacing ||'s with Multiple directives.") [Select]
%ifidn %2,-o
push %1
%elifidn %2,-d
push %1
%elifidn %2,-b
push %1
%elifidn %2,-s
push %1
%endif

About Bryant Keller
bkeller@about.me