| UMBC CMSC 211 |
A = 3; /* assigns the value of three to the memory location you named A */ x = A; /* the memory location x gets the value used at location A or three */ p = &A; /* P now holds the address of the memory location you named A */
As you remember, we can write something like this:
| A | DB | 24 |
| B | DW | 1234 |
| mov | bx, B | ; moves the contents of B to bx | |
| mov | bx, OFFSET B | ; moves the address of B to bx |
char name[10];
| A | DB | 0Ah, 1Ah, 2Ah, 3Ah, 6 dup (?) |
| A | DB | 0Ah |
| DB | 1Ah | |
| DB | 2Ah | |
| DB | 3Ah | |
| DB | 6 dup (?) |
| mov | al, A | ; moves the contents of A to al | |
| mov | al, [ A + 3 ] | ; moves the address of A plus 3 to al (which holds 3Ah!) |
Notice that the following are not the same thing!!!!!
| mov | al, A + 3 | ; moves 3Ah into al | |
| mov | al, [ A ] + 3; | ; moves 0Ah plus 3 (0Dh) into al |
If you to get the address of pointed to by [ a + 3 ], you would use:
| mov | ax, OFFSET [A + 3] | ; moves address of where the ; byte 3Ah is into ax |
| AA | DB | 0Ah, 1Ah, 2Ah, 3Ah, 4Ah, 5Ah, 6Ah, 7Ah |
| BB | DB | 0Bh, 1Bh, 2Bh, 3Bh |
| CC | DB | 0Ch, 1Ch, 2Ch, 3Ch, 4Ch, 5Ch |
| Label | AA: | BB: | CC: | |||||||||||||||||
| Contents | 0A | 1A | 2A | 3A | 4A | 5A | 6A | 7A | 0B | 1B | 2B | 3B | 0C | 1C | 2C | 3C | 4C | 5C | ||
| Offset | AA BB-8 CC-12 |
AA+1 BB-7 CC-11 |
AA+2 BB-6 CC-10 |
AA+3 BB-5 CC-9 |
AA+4 BB-4 CC-8 |
AA+5 BB-3 CC-7 |
AA+6 BB-2 CC-6 |
AA+7 BB-1 CC-5 |
AA+8 BB CC-4 |
AA+9 BB+1 CC-3 |
AA+10 BB+2 CC-2 |
AA+11 BB+3 CC-1 |
AA+12 BB+4 CC |
AA+13 BB+5 CC+1 |
AA+14 BB+6 CC+2 |
AA+15 BB+7 CC+3 |
AA+16 BB+8 CC+4 |
AA+17 BB+9 CC+5 |
It is important to notice that the offset can be a positive or negative number and that there is nothing preventing this. Array-bound checking is only accomplished in high-level languages with the addition of additional code that you normally don't see! This is why in C, if you exceed the boundary of an array, you don't get an error message unless you attempt to use memory that is not available.
Whenever you use OFFSET, you are referring to a word! For mov instructions, you must have a sixteen bit register as the destination!
Looking at a word array, we can have:
INCLUDE PCMAC.INC
.MODEL SMALL
.STACK 100h
.DATA
;
A DW 000Ah, 001Ah, 002Ah, 003Ah, 004Ah
;
.CODE
template PROC
;
mov ax, @data
mov ds, ax
;
mov ax, OFFSET A
mov bx, [ A + 3] ;Danger!!!!
;
_Exit
template ENDP
END template
When we run this, we get:
1A3B:0000 0A 00 1A 00 2A 00 3A 00 4A 00 4E 42 4E 1A3B:000D 42 30 38 20 02 00 00 00 00 00 00 01 00
1A3A:0000 B83B1A MOV AX,1A3B ;Really mov ax, @data 1A3A:0003 8ED8 MOV DS,AX 1A3A:0005 B80000 MOV AX,0000 1A3A:0008 8B1E0300 MOV BX,WORD PTR [0003] 1A3A:000C B44C MOV AH,4C 1A3A:000E CD21 INT 21
AX = 0000 BX = 2A00 CX = 0000 DX = 0000 SP = 0100 BP = 0000 SI = 0000 DI = 0000 DS = 1A3B ES = 1A2A SS = 1A3C CS = 1A3A IP = 000C FL = 3202 NV UP EI PL NZ NA PO NC
The most important difference is when a program is loaded into a different location in memory, the addresses change but the numbers do not!
If A and B are addresses and n a ordinary number, then we can legally do:
Some examples are:
| A + 14 | address |
| B - A | number |
| CW - AW | number |
| AW + ( B - A ) | address Remember B - A is a number that puts this into the form of A + n |
Here is an example:
.model small
.stack 100h
.data
msg DB 'This is a test', 10, 13, '$'
msglen DW $ - msg
msg1 DB 'Its length is $'
.code
EXTRN PutDec : NEAR
main PROC
include pcmac.inc
_Begin
_PutStr msg
_putStr msg1
mov ax, msglen
call PutDec
_PutCh 10, 13
_exit
main ENDP
END main
This says that the length is 17, which is longer than the string that appears on the string. Why???? Because in memory, the 10, 13, and '$' each occupy one byte and is included in the length.
| AWord | DW | 1234h |
| 34h | 12h |
Words in assembly language source code files
and words in registers have bytes in their normal order. Words in
memory have their bytes swapped!
Moving a word to or from memory automatically swaps bytes.
Once a label for a variable is defined with a size, it keeps that size of word or byte that it was give, unless you cast or coerce or override it:
Aword DW 1234h
...
mov al, BYTE PTR AWord ; al now has 34h