I somehow got stuck on a simple quest: copying a word from memory
into a register. Here's what I do:
void myfunc(char *buff) {
_asm {
mov ax, [buff]
}
}
This is inline assembly within OpenWatcom. My understanding so far was
that:
mov ax, buff ; copies buff (pointer) into AX
mov ax, [buff] ; copies *buff (first word at memory location) into
AX
But that's not what happens now.
Whether I use "mov ax, buff" or "mov ax, [buff]", the result is the
same: AX gets the address of buff and never the value under it.
What am I missing?
I must add that it works when I do this:
void myfunc(char *buff) {
_asm {
mov bx, buff
mov ax, [bx]
}
}
I'd like to understand why my first version isn't producing what I
expect, though... Any ideas?
Mateusz
I somehow got stuck on a simple quest: copying a word from memory into a register. Here's what I do:
void myfunc(char *buff) {
_asm {
mov ax, [buff]
}
}
This is inline assembly within OpenWatcom. My understanding so far was
that:
mov ax, buff ; copies buff (pointer) into AX
mov ax, [buff] ; copies *buff (first word at memory location) into AX
On 12.11.2021 14:35, Mateusz Viste wrote:
I somehow got stuck on a simple quest: copying a word from memory
into a register. Here's what I do:
void myfunc(char *buff) {
_asm {
mov ax, [buff]
}
}
This is inline assembly within OpenWatcom. My understanding so far
was that:
mov ax, buff ; copies buff (pointer) into AX
mov ax, [buff] ; copies *buff (first word at memory location)
into AX
There is no such x86 instruction. For indirect addressing you have to
use a register.
mov ah, 2
mov dl, [buff]
This instruction doesn't exist, the compiler uses instead:
mov dl, buff
To illustrate/understand the "issue", I wrote a little test program.
; print first char of cmdline tail
cpu 8086
org 0x100
; does not work (prints the character 0x82)
mov ah, 2
mov dl, [buff]
int 0x21
; works (prints the character at location 0x82)
mov ah, 2
mov dl, [0x82]
int 0x21
; game over
mov ax, 0x4c00
int 0x21
buff dw 0x82
2021-11-12 at 19:19 +0100, Herbert Kleebauer wrote:
mov ah, 2
mov dl, [buff]
This instruction doesn't exist, the compiler uses instead:
mov dl, buff
Well, no - in this specific example "mov dl, [buff]" does exist.
It
loads whatever is at the location pointed out by buff (here: the word
0x82). But note that my previous program was an actual assembly
listing, not an assembly-inside-C abomination like in the first post.
"mov dl, [buff]" is, in fact, the same instruction as in "mov dl,
[0x82]", it is just that the assembler substitutes "buff" by its offset
at compile time:
00000000 B402 mov ah,0x2
00000002 8A161501 mov dl,[0x115]
00000006 CD21 int 0x21
00000008 B402 mov ah,0x2
0000000A 8A168200 mov dl,[0x82]
0000000E CD21 int 0x21
00000010 B8004C mov ax,0x4c00
00000013 CD21 int 0x21
00000015 82 db 0x82
00000016 00 db 0x00
My foolish mistake was to expect a similar behavior within an inline
assembly block when referencing a C pointer (which is different from an assembly offset and implies - as you correctly pointed out in your
first reply - an extra layer of indirection).
I somehow got stuck on a simple quest:
copying a word from memory into a register.
You might need to declare "buff" as a C variable, with both a
"volatile" keyword and as a pointer. E.g., perhaps (untested):
volatile unsigned char *buff=0xb800;
Then in the _asm{} section, the compiler should recognize "buff" as a
C variable, use the assigned address, and not optimize away the code
(due to the volatile):
mov ax,[buff]
Does the OpenWatcom assembler allow to use [] as normal
parenthesis like in [3+4]*5 ?
That is correct indeed, thanks. I have been confused by what "buff"
truly is. It is still weird that buff and [buff] are the same, but
that's certainly due to the magic introduced by the C compiler to
reference C variables within the inline assembly block.
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 415 |
Nodes: | 16 (2 / 14) |
Uptime: | 167:05:59 |
Calls: | 8,708 |
Calls today: | 2 |
Files: | 13,270 |
Messages: | 5,952,234 |