ASM 8086 : Reading the value of a variable is different from the value assigned to the variable - variables

I'm writing a little program in Assembly 8086 and I have to use variables.
So I have a variable that is defined in the data segment :
myVar BYTE 3,0
Afterwards in my code I have to acces the variable and use it's value. But the program did not work like expected. So I searched the error in my code and I found that when I acces "myVar", the value is different from the value I assigned to it.
When I print the contents of "myVar" it prints 173 instead of 3 :
xor dx, dx
mov dl, myVar
push dx
CALL tprint
"tprint" is a function I wrote, that will display the number passed as argument via the stack. So in this case it will print the content of the DX register.
When I put 3 in dx and then print it, it prints 3, so "tprint" works fine :
xor dx, dx
mov dl, 3
push dx
CALL tprint
So the problem is that when I move the contents of the variable "myVar" in the DL register, the wrong value is put in DL (another value than the value assigned to "myVar") :
xor dx, dx
mov dl, myVar ; DL != 3 --> why???
I really don't understand this behaviour, I searched a lot of sites and they all do it this way, why does it works fine for them and not for me?
Remark : The "tprint" function is a function for printing signed numbers using two's complement method.
Thanks for your help!

When you move a value from a register, you want to use brackets to move the actual value and not the memory address. So for
mov dl, myVar
you're likely moving just the pointer instead of the value.
See this link

Related

Why does the Rust compiler perform a copy when moving an immutable value?

My intuition must be wrong about moves and copies. I would expect the Rust compiler optimize away moves of an immutable value as a no-op. Since the value is immutable, we can safely reuse it after the move. But Rust 1.65.0 on Godbolt compiles to assembly that copies the value to a new position in memory. The Rust code that I am studying:
pub fn f_int() {
let x = 3;
let y = x;
println!("{}, {}", x, y);
}
The resulting assembly with -C opt-level=3:
; pub fn f_int() {
sub rsp, 88
; let x = 3;
mov dword ptr [rsp], 3
; let y = x;
mov dword ptr [rsp + 4], 3
mov rax, rsp
...
Why does let y = x; result in mov dword ptr [rsp + 4], 3 and mov rax, rsp? Why doesn't the compiler treat y as the same variable as x in the assembly?
(This question looks similar but it is about strings which are not Copy. My question is about integers which are Copy. It looks like what I am describing is not a missed optimization opportunity but a fundamental mistake in my understanding.)
I would not call it a fundamental mistake in your understanding, but there are some interesting observations here.
First, println!() (and the formatting machinery in particular) is surprisingly hard to optimize, due to its design. So the fact that with println!() it was not optimized is not surprising.
Second, it is generally not obvious it is OK to perform this optimization, because it observably make the addresses equivalent. And println!() takes the address of the printed values (and passes them to an opaque function). In fact, Copy types are harder to justify than non-Copy types in that regard, because with Copy types the original variable may still be used after a move while with non-Copy types it is possible that not.
If you change your example like this
pub fn f_int() -> i32 {
let x = 3;
let y = x;
// println!("{}, {}", x, y);
x+y
}
the optimisation takes place
example::f_int:
mov eax, 6
ret
The println!() macro (as well as write!()...) takes references on its parameters and provides the formatting machinery with these references.
Probably, the compiler deduces that providing some functions (that are not inlined) with references requires the data being stored somewhere in memory in order to have an address.
Because the type is Copy, the semantics implies that we have two distinct storages, otherwise, sharing the storage would have been an optimisation for a move operation (not a copy).

Accepts and displays one character of 1 through 9 using assembly code in c

Can someone please explain me each line of this assembly code?
void main(void){
_asm{
mov ah,8 ;read key no echo
int 21h
cmp al,‘0’ ;filter key code
jb big
cmp al,‘9’
ja big
mov dl,al ;echo 0 – 9
mov ah,2
int 21h
big:
}
}
PS: I am new to assembly in c/c++.
Per the docs, the return value is in al, not ah. That's why it compares to al.
Edit: Adding more detail:
Looking at this code:
mov ah,8 ;read key no echo
int 21h
Think of this like a function call. Now normally a function call in asm looks like call myroutine. But DOS used interrupts to allow you to call various operating system functions (read a key from the keyboard, read data from a file, etc).
So, executing the int 21h instruction called the operating system. But how was the operating system supposed to know which OS function you wanted? Typically by putting a value in ah. If you search, you can find a number of resources that show listings of all the int 21h functions (like this). The numbers on the right are the values you put in ah.
So, mov ah,8 is preparing to call the "Wait for console input without echo" function. mov ah,2 is "Display output." Other registers are used to pass various parameters to the function being called. You need to read the description of the specific interrupt to understand what goes where.
Note that NONE of this is related to "writing inline asm in C." This is just how to call OS function from C code running under DOS. If you aren't running under DOS, int 21 won't work.

Assembly - assign int value to string

It is possible to assign an int value to a string in assembly?
For example, I put >> rat = 2, and when I call a program that uses the variables, if I put >> rat + 2, it has to return 4.
And, if it's possible, which is the best way to do it?
Any help will be appreciated.
It sounds like you are wanting to store an integer in a variable, that just happens to be named using a string? That's very different from how rkhb interpreted your question, but I think it is more in line with your actual question, judging from the tags you've used.
There are two basic types of variables supported in NASM: initialized data and uninitialized data.
With initialized data, you assign a static value when you declare the variable. Actually, initialized data is more like a constant, but you name it symbolically. DB (Declare Byte), DW (Declare Word), DD (Declare Doubleword), and DQ (Declare Quadword) are the commands used to declare initialized data. So you could do:
rat DD 2
And then somewhere in your code, do:
mov eax, DWORD [rat]
add eax, 2
; eax now contains 4
With uninitialized data, you are basically just reserving space to hold data. This data is not initialized statically; you fill it at run-time. You use RESB (Reserve Byte), RESW (Reserve Word), RESD (Reserve Doubleword), and RESQ (Reserve Quadword) for this; for example:
rat RESD 1 ; reserve space for 1 DWORD-sized value
And then later in your code, you would go:
call GetValue ; returns value in EAX
mov DWORD [rat], eax ; store value in 'rat'
This is all explained in Chapter 3 of the NASM manual.
That's wasn't what I was looking for, but thanks
I'm trying to make a calculator with variables with NASM
So, as a Casio calculator (for example), that you can put variables like X, Y, M, Z and others, and then you can assign values to those variables
That is what I'm looking for, not inside the code, but in screen.
Again, thanks for help, it helped me with another error with my code

obj-c pass struct pointer to arm assembly function - corruption [duplicate]

This question already has an answer here:
return floats to objective-c from arm assembly function
(1 answer)
Closed 6 years ago.
I have a structure in obj-c. I pass a pointer to this structure to an arm assembly function that i've written. When i step into the code i see the pointer get successfully passed in and i can access and modify the values of the structure elements from within my asm code. Life is good - until i return from the asm function. After returning to the calling obj-c code the structure values are all hosed. I can't figure out why. Below are the relevant pieces of my code.
struct myValues{ // define my structure
int ptr2A; // pointer to first float
float A;
float B;
float C;
float D;
float E;
float F;
}myValues;
struct myValues my_asm(int ptr2a, float A, float B, float C, float D, float E, float F); // Prototype for the ASM function
…code here to set values of A-F...
float* ptr2A = &myValues.A; //get the memory address where A is stored
myValues.ptr2A = ptr2A; //put that address into myValues.ptr2A and pass to the ASM function
// now call the ASM code
myValues = my_asm(myValues.ptr2A, myValues.A, myValues.B, myValues.C, myValues.D, myValues.E, myValues.F);
Here is relevant part of my asm code:
mov r5, r1 // r1 has pointer to the first float A
vdiv.f32 s3, s0, s0 //this line puts 1.0 in s3 for ease in debugging
vstr s3, [r5] // poke the 1.0 into the mem location of A
bx lr
When i step through the code everything works as expected and i end up with a 1.0 in the memory location for A. But, once i execute the return (bx lr) and return to the calling obj-c code the values in my structure become garbage. I've dug through the ABI and AACPS (as successfully as a novice probably can) but can't get this figured out. What is happening after that "bx lr" to wack the structure?
Below is "Rev 1" of my asm code. I removed everything except these lines:
_my_asm:
vdiv.f32 s3, s0, s0 // s3 = 1.0
vstr s3, [r1]
bx lr
Ok, this was solution for me. Below is "Rev 2" of the relevant pieces of my obj-c code. I was conflating passing a pointer with passing a copy of the structure - totally hose. This code just passes a pointer to the first float in my struct...which my asm code picks up from general register r0. Man, i'm hard headed. ;-)
void my_asm2(int myptr); // this is my prototype.
This is where i call the asm2 code from my obj-c code:
my_asm2(&myValues.A);
My asm2 code looks like this:
_my_asm2: ; #simple_asm_function
// r0 has pointer to the first float of my myValues structure
// Add prolog code here to play nice
vdiv.f32 s3, s0, s0 //result S3 = 1.0
vstr s3, [r0] // poking a 1.0 back into the myValues.A value
// Add Epilog code here to play nice
bx lr
So, in summary, i can now pass a pointer to my structure myValues to my ASM code and inside my ASM code i can poke new values back into those memory locations. When i return to my calling obj-c code everything is as expected. Thanks to those who helped me fumble along with this hobby. :-)
The solution here is to simply pass a pointer (that points to the memory location of the first float variable in the structure) to the assembly function. Then, any changes the assembly function makes to those memory locations will be intact upon returning to the calling function. Note that this applies to the situation when you are calling assembly code and want that code to operate on an existing data structure (myValues in this case).

Updating variable that lives in the data segment from the stack and its segment

I currently have three segments of memory, my main data segment, stack segment and the segment where my API lives. The following instructions are executed from the data segment, they push the address of cursorRow and welcomeMsg then do a far call to the function in my API segment. The cursorRow variable lives in the main data segment that is calling the API function. The call looks like this:
push cursorRow
push welcomeMsg
call API_SEGMENT:API_printString
How can I alter cursorRow, inside of the segment where my API lives, through the stack? cursorRow needs to be updated from the API. NO API functions alter the data segment. I have tried things like: inc byte [ds:bp+8] and add [ds:bp+8], 1.
Here is the API procedure being called:
printStringProc:
push bp
mov bp, sp
mov si, [bp+6]
.printloop:
lodsb
cmp al, 0
je printStringDone
mov ah, 0x0E ; teletype output
mov bh, 0x00 ; page number
mov bl, 0x07 ; color (only in graphic mode)
int 0x10
jmp .printloop
printStringDone:
; move the cursor down
mov ah, 02h ; move cursor
mov dh, [bp+8]
mov dl, 0 ; column
mov bh, 0 ; page number
int 10h
add [ds:bp+8], 1
pop bp
retf
it prints strings, but the cursorRow variable doesn't correctly update. I hope I'm clear enough on my issue. It's hard to explain :D
This is because you passed the pointer to cursorRow, not cursorRow itself. When you perform
inc [ds:bp+8]
you: 1) get the value of bp, 2) add 8, 3) assume the result is a pointer in ds, 4) increment the value stored there (the pointer to cursorRow). Since the pointer is stored on the stack, you are incrementing the pointer when you do this. What you need to do is take the pointer off of the stack and increment the value that points to.
mov bx, [bp+8]
inc [bx]
This code: 1) gets the value of bp, 2) adds 8, 3) assumes the result is a pointer in ss, 4) load the value stored there (the pointer to cursorRow) into bx, 5) assumes bx is a pointer in ds, 6) increments the value stored there (the value of cursorRow).
It's look like you just pushed the value of cursorRow onto the stack. Without the address you cannot update it. With the address you can easily reference that addresses' value, put it into a register, perform operations on it, then take the value that's in that register and put it into the address of cursorRow.