Page 1 of 1
Jumping to labels with same name as variable
Posted: Sun Feb 27, 2011 1:26 am
by phillid
Hey. I was just wondering whether it's possible to do the following:
Code: Select all
; Assembler Code (duh)
mov [myvar], othervar
jmp [myvar] ; jump to the label specified in [myvar]?
mylabel: jmp mylabel ; Hang
myvar times (256) db '0' ; define variable 'myvar'
othervar db "mylabel" ; define variable 'othervar' with value 'mylabel'
So I want to have a variable that holds a label to jump to, and be able to jump to that variable by putting it in the JMP instruction.
I have a question:
- Will the computer jump to the
address that [myvar] is held at, instead of the
label that [myvar] contains?
Thanks for any help!
Re: Jumping to labels with same name as variable
Posted: Sun Feb 27, 2011 2:05 am
by Brendan
Hi,
phillid wrote:So I want to have a variable that holds a label to jump to, and be able to jump to that variable by putting it in the JMP instruction.
Assembly language doesn't have variables, and labels are just a way to give addresses names. Everything is either an address or data at an address.
Even though "jumping to data at an address" doesn't make much sense in practice, it is entirely possible. For example:
Code: Select all
jmp foo ;JMP to the data at an address
foo: dd 0 ;Some data at an address
It's also possible to jump to the address stored at another address. This is called an indirect jump:
Code: Select all
jmp [foo] ;JMP to the address stored at an address
foo: dd bar ;Some data at an address
bar: ret
Cheers,
Brendan
Re: Jumping to labels with same name as variable
Posted: Sun Feb 27, 2011 1:03 pm
by Fanael
Brendan wrote:Even though "jumping to data at an address" doesn't make much sense in practice, it is entirely possible.
It makes very much sense and most if not all programs do this very very often, actually. Code is data, too. What are subroutine calls, conditional branches,
agus araile, if not "jumping to data at an address"?
Re: Jumping to labels with same name as variable
Posted: Sun Feb 27, 2011 1:49 pm
by Combuster
There is a difference between jumping to an address (direct), and jumping to an address described by data at another address (indirect).
Anyway, all conditionals are jumps to addresses, and most function calls are. Virtual functions and function pointers are jumps to location stored at address, and switch statements are often optimized to jumps to location stored at nth entry in list (another indirect data at address)
That said, you can split any indirect jump into a load and a direct jump.
Re: Jumping to labels with same name as variable
Posted: Mon Feb 28, 2011 12:16 am
by phillid
Well, I have found a function called 'cmpstr' which is meant to compare two strings but I don't have a way to tell it which label to jump to if the strings are equal, or not. I thought I could have a 'variable' that I could set.
Does anyone have any suggestions?
Here's the cmpstr code ('put' puts text on the screen):
Code: Select all
string1 db 'this is string 1',0
string2 db 'this is string 2',0
cmpstr:
lea si, string1 ; ds:si points to first string
lea di, string2 ; ds:di points to second string
dec di
inc di ; ds:di -> next character in string2
lodsb ; load al with next char from string 1
cmp [di], al ; compare characters
jne NotEqual ; jump out of loop if they are not the same
cmp al, 0 ; they are the same, but end of string?
jne cmpstr ; no - so go round loop again
; ------------------------------------
; Strings are equal
; ------------------------------------
mov si, equalmsg
call put
retn ; continue with rest of program
; ------------------------------------
; Strings are not equal
; ------------------------------------
NotEqual:
mov si, notequalmsg
call put
cmpstrd:
retn
Re: Jumping to labels with same name as variable
Posted: Mon Feb 28, 2011 2:09 am
by Solar
It's a
bad sign when
I can answer someone's ASM question...
phillid wrote:Well, I have found a function called 'cmpstr' which is meant to compare two strings but I don't have a way to tell it which label to jump to if the strings are equal, or not.
Code: Select all
; ...
mov si, equalmsg
; ...
mov si, notequalmsg
; ...
retn
These here are the two "outcomes" of the function, which obviously has been designed to point
si at some message depending on outcome. You want to "jump to label" instead. Obviously you have to modify the function.
Put two addresses (labels) into specific registers, and have the function return one of them depending on whether the strings are equal or not. After calling the function, jump to the "return" address.
Code: Select all
mov bx, label_if_equal
mov cx, label_if_not_equal
call cmpstr
jmp [ax]
cmpstr:
; ...
mov ax, bx ; instead of mov si, equalmsg
; ...
mov ax, cx ; instead of mov si, notequalmsg
; ...
retn
Which, of course and now that I think of it, is just a more complicated version of:
Code: Select all
mov bx, label_if_equal
mov cx, label_if_not_equal
jmp cmpstr
cmpstr:
; ...
jmp bx ; instead of mov si, equalmsg
; ...
jmp cx ; instead of mov si, notequalmsg
Does that help you?
Re: Jumping to labels with same name as variable
Posted: Mon Feb 28, 2011 11:16 pm
by phillid
Yeah, thanks, but that's what I was saying in my example in the first place!
Don't get me wrong, I'm not mad at you, I'm just a bit annoyed at others for not giving me a simple, short answer.
They mislead me!
Oh well!
Thanks anyway!
Re: Jumping to labels with same name as variable
Posted: Tue Mar 01, 2011 12:39 am
by Solar
All I did was replying to your last post:
I don't have a way to tell it which label to jump to if the strings are equal, or not.
And I can say from experience, there is no misleading, only misunderstanding.
Re: Jumping to labels with same name as variable
Posted: Tue Mar 01, 2011 1:50 am
by Combuster
I think he's either trying to implement a symbol table of sorts, or the concept of return values has gone amiss:
Code: Select all
CALL compare ; in this example, ZF (zero/equal) gets set to the result
; like a rep cmpsb would do
JE .equal
.notequal:
(...)
.equal:
(...)
Otherwise, you'll want a construction somewhat like the following:
Code: Select all
typedef struct entry
{
const char * name;
int (*target)(void); // function pointer
} entry;
static entry * table = {
{"name1", &function1},
{"name2", &function2},
{NULL, NULL}
};
int lookup_and_call(const char * functionname)
{
entry * current = table;
while(current)
{
if (strcmp(functionname, current->name) == 0) return current->target();
current++;
}
}