Author Topic: ASM and variables  (Read 13277 times)

Offline montraydavis

  • Jr. Member
  • *
  • Posts: 6
ASM and variables
« on: January 06, 2011, 04:23:41 PM »
I have searching Google for countless hours trying to figure out how to add two strings together in ASM, as well as manipulate integers.

I have tried

Code: [Select]
age db 0

mov age,30

Code: [Select]
age db 0

inc age

Code: [Select]
age db 0

imul age, 30, 30

Code: [Select]
age db 0

mul age, 30, 30

but I always get the error

Quote
error: invalid combination of opcode and operands

I have also tried doing similar functions with strings, and get the same error. Not sure what I am doing wrong....

Thanks in advance. I'm not asking for a hand-me-down, or hold-my-hand, but at least some type of guidance or explanation as to why the above functions do not work. Thanks (:

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2381
  • Country: us
Re: ASM and variables
« Reply #1 on: January 06, 2011, 08:17:14 PM »
Well, use valid combinations of opcodes and operands!

http://www.nasm.us/xdoc/2.09.04/html/nasmdoc2.html#section-2.2.2

"The rule is simply that any access to the contents of a memory location requires square brackets around the address, and any access to the address of a variable doesn't."

So:

Code: [Select]
age db 0

mov byte [age], 30
inc byte [age]

Note that Nasm doesn't remember "types", so you'll have to specify an operation size in these cases. If there were a register involved, the size of the register would specify the size of the operation...

Code: [Select]
mov al, [age]
inc al
mov [age], al

Neither "mul" nor "imul" accept the operands you have in mind, so you're S.O.L. on that. Intel/AMD manuals are the "official" documentation on what instructions exist, and their acceptable operands, but you can look here:

http://home.myfairpoint.net/fbkotler/nasmdocc.html#section-A.4.118

To "add two strings together" (I assume you mean "concatenate") will require multiple instructions, and a buffer of sufficient size to hold the resulting string. Making sure you don't overrun the buffer is the hard part!

Best,
Frank


Offline montraydavis

  • Jr. Member
  • *
  • Posts: 6
Re: ASM and variables
« Reply #2 on: January 06, 2011, 10:16:00 PM »
Great.! That works out just fine! Thanks very much for the help. :)

--But what I mean by adding two strings together is the following in C

Code: [Select]


char* p = "GOOGLE";
char* t = "YAHOO";
char* r = "ASK";

strcat(p, t);
strcat(p, r);

--------
Essentially just "a"+"b"="ab"; Any clues on how that works in ASM? Thanks!
« Last Edit: January 06, 2011, 10:32:47 PM by montraydavis »

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2381
  • Country: us
Re: ASM and variables
« Reply #3 on: January 07, 2011, 01:21:17 AM »
Hmmm... well... harumph... looking at the man page for strcat(), it says the destination string must have enough space for the result. I don't see that you've assured that. Does that code work? What happens if you:

Code: [Select]
printf ("%s\n", t);

afterwards? If strcat() does what I understand the man page says, you've got some buggy code there! No wonder the "professionals" produce such a lot of exploitable cruft!

In assembly, I'd allocate a buffer with enough space for the result, copy the first string to the buffer, up to but not including the terminating zero, copy the second string right after that, up to and including the terminating zero, and return the address of the buffer.

Best,
Frank


Offline montraydavis

  • Jr. Member
  • *
  • Posts: 6
Re: ASM and variables
« Reply #4 on: January 07, 2011, 01:25:57 AM »
Sorry for the confusion, but, I am not actually using C.... That C example was just to show you want I want to do in ASM.

In other words, convert the strcat C function to ASM. Thanks for the response.!

Offline cm

  • Jr. Member
  • *
  • Posts: 65
Re: ASM and variables
« Reply #5 on: January 07, 2011, 04:36:10 AM »
Try loading one byte and storing it elsewhere. Then try some more. Then figure out how to address memory using registers.
C. Masloch

Offline montraydavis

  • Jr. Member
  • *
  • Posts: 6
Re: ASM and variables
« Reply #6 on: January 07, 2011, 03:48:33 PM »
Well, I used the following

Code: [Select]
Age db "Hello", 0
Other db ", Josh", 0
mov [Age], Other

It somewhat works, but, it moves the BDAY value into the first bits of age.
IE:

Instead of resulting in "Hello, Josh", I get ", Josh". How would I move the Other value into Age, but, after the last character?
« Last Edit: January 08, 2011, 12:29:26 AM by montraydavis »

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2381
  • Country: us
Re: ASM and variables
« Reply #7 on: January 07, 2011, 06:59:56 PM »
Code: [Select]
mov [Age], Other

I'm surprised this assembles without a size specifier, but in any case, you're loading the address of "Other" into "[Age]". The fact that it apparently spells "sir" is coincidence.

To start with something really simple, "a" + "b" = "ab"...

Code: [Select]
section .data
str1 db "a", 0
str2 db "b", 0

section .text
;mov [str1 + 1], [str2]  ; Nope! No such instruction!
mov al, [str2]
mov [str1 + 1], al

Now we've got "ab"... but we haven't got it zero-terminated, and we haven't left a space for the zero! If I understand the man page for strcat() correctly, it expects the "destination" string to have space for the concatenated characters, plus the terminating zero(!). I can't believe that's right, but okay...

Code: [Select]
str1 db "a", 0, 0

There! :) Pretty limited, though! We could do a slightly more "general" version...

Code: [Select]
CATSIZ equ 20 ; ought to be enough, unless you've got a long name

str1 db "Hello, ", 0
times CATSIZ db 0

str2 db "Josh!", 10, 0 ; or 13, 10 for dos, if you want a newline

Now I suppose we could do:

Code: [Select]
mov al, [str2]
mov [str1 + 7], al
mov al, [str2 + 1]
mov [str1 + 8], al
mov al, [str2 + 2]
mov [str1 + 9], al
...

This would get old real quick! I'm not even sure I've got 'em counted right in the first place. As Christian suggests, it's time to learn addressing with registers! So far, you haven't told us what size of registers you'll be using - 16-bit, 32-bit, or 64-bit. I'll go with 32-bit, since it's what I'm used to, but I'll try to keep it 16-bit compatible (it makes a difference!). 64-bit code is above my pay grade! :)

Code: [Select]
section .data
CATSIZ equ 20 ; ought to be enough, unless you've got a long name

str1 db "Hello, ", 0
times CATSIZ db 0

str2 db "Josh!", 10, 0 ; or 13, 10 for dos, if you want a newline

section .text
_start: ; or so, per your output format, etc.

  mov edi, str1 ; address(!) of str1
  mov esi, str2
  mov ecx, CATSIZ
findend:
  mov al, [edi]
  inc edi
  cmp al, 0
  jnz findend
; we want to overwrite the zero, and we've gone one past it
  dec edi
copystr:
  mov al, [esi]
  mov [edi], al
  cmp al, 0  ; are we at the end of str2?
  jz endstrcat
  inc esi
  inc edi
  dec ecx
  jnz copystr

; we're at the end of the "extra space" in str1!
; Terminate what we've got, and quit.
; again, we've gone "one past".
  mov byte [edi - 1], 0
endstrcat:

; print out your masterpiece
; exit cleanly

That's untested, and may well have errors. It is far from optimal. Should be a subroutine. Etc. But I think it's the general idea of what you need to do to "add two strings together". There are "string instructions" (lodsb, stosb, scasb, movsb,...) that might be helpful, but they do pretty much the same thing as above. As I mentioned, I'd probably use a separate "result buffer", rather than demand that "str1" had space at the end of it (and trash "str1" for any further use...), but still the same idea. Told ya it would take multiple instructions! :)

Best,
Frank


Offline cm

  • Jr. Member
  • *
  • Posts: 65
Re: ASM and variables
« Reply #8 on: January 07, 2011, 09:32:36 PM »
Code: [Select]
mov [Age], Other

I'm surprised this assembles without a size specifier,

Yes. It should in fact not assemble. Please post the exact code you tried, not a transcript.

but in any case, you're loading the address of "Other" into "[Age]".

Exactly. Please learn to differentiate between an immediate address value, and a memory access.

If I understand the man page for strcat() correctly, it expects the "destination" string to have space for the concatenated characters, plus the terminating zero(!). I can't believe that's right, but okay...

This is off topic, but that is in fact one method of buffer overflows.

I'll go with 32-bit, since it's what I'm used to, but I'll try to keep it 16-bit compatible (it makes a difference!).

Yeah, that should work for 16-bit addressing too (except that of course, we would have to replace edi and esi by di and si). With 16-bit addressing there's basically [indexreg], [indexreg+basereg], [basereg], variants of these with immediate offsets, and a single immediate address. "indexreg" must be si or di, while "basereg" must be bx or bp. With 32-bit addressing you can use each register alone, and some simple calculations are possible besides adding registers and offsets.

But I think it's the general idea of what you need to do to "add two strings together".

I would just advise not to let any of this C++ style operator overloading lingo get to you. You cannot add strings, there is no meaningful "add" operation inherent to string operands. For this task I would instead refer to concatenating two strings, or to appending one string to another. Additionally, (like in C) there is no inherent "string" data type in assembly language - you have to work with one of the data types available, such as a byte. (A byte may or may not be the same as a "character" of a "string", depending on the string's encoding.) With that in mind, we can say that our objective is appending two byte sequences. Code to do that is a lot easier to write than code that "adds strings".

To clarify this, I don't think referring to this objective as "appending strings" is bad. But to implement this in assembly language (as for any other programming languages), you have to go down to the basics of what "appending strings" really means. To implement it, you have to think about what "appending" and "string" mean.

(However, I do think using the term "add" to mean "append" is bad.)
« Last Edit: January 07, 2011, 09:40:33 PM by cm »
C. Masloch