0

I am working on some code for my port of MikeOS. It is written in NASM x86 16 bit assembly. I am trying to change a variable that I made to have a different value. It compiles with no errors, but when I call os_print_string, it prints some wierd ASCII characters. Here is the code:

    BITS 16
    ORG 32768
    %INCLUDE "mikedev.inc"



start:
    mov si, test2          ; give si test 2 value
    mov [test1], si        ; give test 1 si's value
    mov si, test1          ;now give test1's value to si
    call os_print_string   ; and print

test2 db "adsfasdfasdf", 0
test1 db "asdf", 0

This code is redundant, I know. I just need a n explanation on how to change a variable's value. Thaks in advance!

-Ryan

Ryan N.
  • 1
  • 1
  • 1
  • 3
    What you're doing is taking the address of `test2` and storing it in the first two bytes of `test1` (i.e. where the first `"ad"` used to be). You can't change the address of `test1` at runtime. What you can do is copy the contents (i.e. all the characters) from `test2` to `test1`. Keep in mind that you don't have enough room at `test1` to hold all the characters from `test2`. – Michael Nov 20 '14 at 06:31
  • In reply to Michael: Thank you for your comment, but I guess I probably was not being clear enough. This project that I am making for MikeOS is a scripting language. I am trying to figure out how to assign one variable's value to another (i.e. string a = b;). – Ryan N. Nov 21 '14 at 01:52
  • In that case you probably wouldn't implement your strings the way you have in your current code. `test1` and `test2` are more akin to a `char * const` in C, i.e. pointers that can't be changed to point anywhere else. – Michael Nov 21 '14 at 06:26

1 Answers1

1

Another good old question, here is the answer you waited for 6.83 years :)

BITS 16
ORG 32768
%INCLUDE "mikedev.inc"

start:
mov si, test2
mov di, test1

.loop:
lodsb
or al, al
je .done
stosb
jmp .loop

.done:
mov si, test1
call os_print_string

test2 db "adsfasdfasdf", 0
test1 db "asdf        ", 0

Make sure the char arrays have the same length or this will break ^^ But i am sure you know that by now ^^

RAVN Mateus
  • 560
  • 3
  • 13
  • `or al, al` is an old inefficient idiom. `test al,al` is [the normal good way](https://stackoverflow.com/questions/33721204/test-whether-a-register-is-zero-with-cmp-reg-0-vs-or-reg-reg) to set FLAGS from a register. – Peter Cordes Sep 28 '21 at 16:08
  • Your loop doesn't copy the terminating 0 byte, so it won't work well if the source isn't the same length as the string that was previously in the destination buffer. You could just lodsb/stosb / `test al,al` / `jnz .loop` to stop *after* copying the 0 with a standard loop structure. – Peter Cordes Sep 28 '21 at 16:10
  • I am apparently not up to date, every old thing i read stated that using or reg, reg instead of test or cmp is a easy to do micro optimization. Also, i didnt care about the zero since test2 would be longer than test1 if i didn't insert the spaces, effectively fucking up some other data stored behind test1 by chance anyways. – RAVN Mateus Sep 28 '21 at 17:32
  • If test2 is *shorter*, then you need to copy a terminator. Also, I didn't say longer than the buffer, I said longer than the string it was currently holding. e.g. if after some other stuff test1 was holding `db "xyz", 0, "xyzxyzxyz", 0`, and you copied in a string that ended in the middle of the 2nd block of xyz, reading test1 as a C string would include the trailing garbage up to the end of the 2nd zero byte. – Peter Cordes Sep 28 '21 at 17:36
  • Also, since avoiding copying the terminator is making your loop less efficient (test/jcc *and* a jmp since you didn't peel the first partial iteration and "rotate" the loop to put the condition at the bottom), it's basically a win to copy that last byte even if it's not needed. – Peter Cordes Sep 28 '21 at 17:37