The array s, defined as:
char s[5] = {'A', 'B', 'C', 'D', 'E'};
s db 'A', 'B', 'C', 'D', 'E'
is represented in memory by:
| Index | 0 | 1 | 2 | 3 | 4 |
| s | A | B | C | D | E |
| Displacement | 0 | 1 | 2 | 3 | 4 |
| Offset | 123016 | 123116 | 123216 | 123316 | 123416 |
The array x, defined as:
int x[4] = {45, 67, -23, 58}
x dd 45, 67, -23, 58
is represented in memory by:
| Index | 0 | 1 | 2 | 3 |
| x | 45 | 67 | -23 | 58 |
| Displacement | 0 | 4 | 8 | 12 |
| Offset | 124016 | 124416 | 124816 | 124C16 |
|
|
| C++ | Assembler | ||||||||||||||||||||||||
// Convert upper to lower case by setting // bit 5 to a 1 void main(void) {
int i;
char s[5] = {'A', 'B', 'C', 'D', 'E'};
for(i=0; i<=4; i++)
s[i] = s[i] | 0x20;
}
|
.data s db 'A', 'B', 'C', 'D', 'E' .code main proc near Mov eSi, 0 for: Cmp eSi, 4 Jbe do Jmp endfor do: Or s[eSi], 20h Inc eSi Jmp for endfor: invoke ExitProcess, 0 main Endp End main |
| C++ | Assembler | ||||||||||||||||||||
// Sum array x
void main(void) {
int i, Sum;
int x[4] = { 45, 67, -23, 58};
Sum = 0;
for(i=0; i<=3; i++)
Sum = Sum + x[i];
}
|
.data Sum dd ? x dd 45, 67, -23, 58 .code main proc near Mov eAx, 0 Mov eSi, 0 for: Cmp eSi, 3*4 Jbe do Jmp endfor do: Add Ax, x[eSi] Add eSi, 4 Jmp for endfor: Mov Sum, eAx invoke ExitProcess, 0 main Endp End main |
Indexing Array Parameters - Arrays in C++ are passed to a function using call by reference, only the starting offset of the array is passed. The array can be indexed in Assembler using two registers, one to hold the starting offset, the other to hold the index. In the following example, eBx holds the starting offset and eSi holds the index. Assuming eBx=1240 and eSi=4, the instruction:
Mov Ax, [eBx][eSi]would access offset 1244, the effective address of the instruction determined by eBx+eSi = 1240+4. By incrementing or decrementing the index value in eSi (or offset in eBx) each array entry can be accessed.
| C++ | Assembler | ||||||||||||||||||||
// Sum array x using function Sumf
int Sumf(int a[]) { // Pass by reference
int i, result;
result = 0;
for(i=0; i<=3; i++)
result = result + a[i];
return result;
}
void main(void) {
int Sum;
int x[4] = { 45, 67, -23, 58};
Sum = Sumf( x );
}
_______________ | Offset X 1240 | eBp+8 |_______________| | Ret Address | eBp+4 |_______________| | Old eBp | eBp+0 |_______________|
|
.data Sum dd ? x dd 45, 67, -23, 58 Data Ends .code main proc near Push offset x Call Sumf Add eSp, 4 Mov Sum, eAx invoke ExitProcess, 0 main Endp Sumf proc Near Push eBp Mov eBp, eSp Mov eAx, 0 Mov eSi, 0 Mov eBx, [eBp+8] ; eBx = Offset 1240 for: Cmp eSi, 3*4 Jbe do Jmp endfor do: Add eAx, [eBx][eSi] ; Offset 1240 + eSi Add eSi, 4 ; Next index Jmp for endfor: Pop eBp Ret Sumf Endp End main |
|
|
| C++ | Assembler | ||||||||||||||||||||||||
void main(void) {
char s[5] = {'A', 'B', 'C', 'D', 'E'};
char *ps;
for(ps=s; ps<=s+4; ps++)
*ps = *ps | 0x20;
}
|
.data s db 'A', 'B', 'C', 'D', 'E' .code main proc near Mov eSi, offset s ;offset 1230 for: Cmp eSi, offset s+4 ;offset 1234 Jbe do Jmp endfor do: Or [eSi], 20h Inc eSi Jmp for endfor: invoke ExitProcess, 0 main Endp Code Ends End main |
| C++ | Assembler | ||||||||||||||||||||
void main(void) {
int Sum;
int x[5] = { 45, 67, -23, 58};
int *px;
Sum = 0;
for(px=x; px<=x+4; px++)
Sum = Sum + *px;
}
|
.data Sum dd ? x dd 45, 67, -23, 58 .code main proc near Mov eAx, 0 Mov eSi, offset x ; 1240 for: Cmp eSi, offset x + 3*4 ; 124C Jbe do Jmp endfor do: Add eAx, [eSi] Add eSi, 4 Jmp for endfor:Mov Sum, eAx invoke ExitProcess, 0 main Endp End main |
Mov eAx, [eSi] ; eAx = 67would access offset 1244, the effective address of the instruction. By incrementing or decrementing the offset value in eSi each array entry can be accessed.
| C++ | Assembler | ||||||||||||||||||||
int Sumf(int a[]) {
int *pa, result;
result = 0;
for(pa=a; pa<=a+4; pa++)
result = result + *pa;
return result;
}
void main(void) {
int Sum;
int x[5]={45, 67, -23, 58};
Sum = Sumf( x );
}
_______________ | Offset X 1240 | eBp+8 |_______________| | Ret Address | eBp+4 |_______________| | Old eBp | eBp+0 |_______________|
|
.data Sum dd ? x dd 45, 67, -23, 58 ;; Assume x starts at offset 1240 .code main proc near Push offset x ; Offset 1240 Call Sumf Add eSp, 4 Mov Sum, eAx invoke ExitProcess, 0 main Endp Sumf proc Near Push eBp Mov eBp, eSp Mov eAx, 0 Mov eSi, [eBp+8] ; Start of array offset 1240 Mov eCx, eSi Add eCx, 3*4 ; End of array offset 124C = 1240+12 for: Cmp eSi, eCx Jbe do Jmp endfor do: Add eAx, [eSi] Add eSi, 4 ; Next index, move eSi pointer Jmp for endfor: Pop eBp Ret Sumf Endp End main |
eCx = 5;
do {
cout << eCx;
eCx--;
} while (eCx != 0);
|
Mov eCx, 5 do: Mov eAx, eCx Call PutDec while: Loop do |
eCx = 5;
do {
cin >> eAx;
eCx--;
} while (eCx != 0 && eAx != 100);
|
Mov eCx, 5 do: Call GetDec Cmp eAx, 100 while: LoopNe do |
| Mov eDi, offset
s
Mov Al, 'A' Cld ; Direction is increment Stosb ; Mov [eDi], Al and Inc eDi |
![]() |
The more useful example is to fill the entire character array s
with
an 'A'. The example below compares C++, indexing, and string instructions.
The only difference between the above and below example is that the Stosb
is repeatedly executed using the Loop instruction.
| C++ | Indexing | String Store Byte | Repeated String Store Byte |
||||||||||||||||||||||||
| char s[5];
int i; for (i=0; i<=4; i++)
|
.data
s db 5 dup(?) Mov
eDi, 0
|
.data
s db 5 dup(?) Mov eDi, Offset s
do: Stosb while: Loop do |
.data
s db 5 dup(?) Mov eDi, Offset s
rep Stosb |
| Repeat | Loop |
| rep Scasb | do:
ScasB while: Loop do |
| repZ ScasB
repE ScasB |
do:
ScasB while: LoopE do |
| repNZ ScasB
repNE ScasB |
do:
ScasB while: LoopNZ do |
.data
String db "ABCDEFG", 0
gnirtS db " ",0
.code
|
; Reverse src string of length N to dest string
;; void Reverse(char src[], char dest[], int N);
Reverse Proc Near C, src : near ptr byte, dest : near ptr byte, N : dword
Push eSi
Push eDi
Mov eCx, N ;; eCx = N;
Mov eSi, src
Mov eDi, dest ;; eDi = dest;
Add eSi, eCx ;; eSi = src + eCx;
Dec eSi
@@do: Std ;; do {
LodsB ;; Al = *Si--;
Cld ;; *Di++ = Al;
Stosb ;; } while( Cx-- != 0);
@@while:
Loop @@do ;; }
Pop eDi
Pop eSi
Ret
Reverse Endp
|
;; Print a 0 terminated string
PutChar proto
;; void putstr( char s[]) {
putstr Proc Near C, s : near ptr byte
Push eSi
Mov eSi, s ;; eSi = s;
Cld
@@while:
Lodsb ;; while ((Al = [eSi++]) != 0)
Cmp Al, 00 ;; cout << Al;
Jne @@do
Jmp @@endwhile ;; }
@@do:
invoke PutChar
Jmp @@while
@@endwhile:
Pop eSi
Ret
putstr Endp
|
;; Number of characters in 0 terminated string
;; int strlength(char s[]){
strlength Proc Near C, s : near ptr byte
Push eDi
Cld
Mov Al, 0 ;; Terminating 0
Mov eCx, 0 ;; eCx = 0;
Mov eDi, s ;; do { eCx++;
@@do: Inc eCx ;; } while (*s++ != '\0');
Scasb
@@while:
Jne @@do
@@endwhile:
Dec eCx ;; return eCx-1;
Mov eAx, eCx ;; }
Pop eDi
Ret ;; Return maximum in eAx
strlength Endp
|
main Proc near ;; void main(void) {
;; Reverse( String, gnirtS, strlength(String) )
invoke strlength, addr gnirtS
invoke Reverse, addr String, addr gnirtS, eAx
invoke putstr, addr gnirtS ;; putstr( gnirtS )
invoke ExitProcess, 0
main Endp
End main
|
Document last modified: