1

I am working on some assembly homework and am stumped on my last program. If anyone with x86 assembly knowledge is lurking, please feel free to comment on how I might get started with this. Thanks!

problem:

Use a loop with indirect or indexed addressing to reverse the elements of an integer array in place. do not copy the elements to any other array. Also use SIZEOF, TYPE, and LENGTHOF operators to make the program flexible to different arrays.

code so far:

.data
array BYTE 10h,20h, 30h, 40h

.code
main PROC
    call Clrscr

        ;no clue... 

    exit
main ENDP

END main
Oded
  • 489,969
  • 99
  • 883
  • 1,009
darko
  • 2,438
  • 8
  • 42
  • 54
  • 1
    Perhaps start by thinking about how you'd do it in a language with which you're more familiar. – Jerry Coffin Mar 09 '11 at 20:45
  • 1
    Write the answer in C, then compile to assembler and jazz it up to look like you typed it yourself. :D – JUST MY correct OPINION Mar 10 '11 at 13:39
  • you could use stack to push the elements in it and pop them. eg: `arr db 3, 2, 1` `push 3`, `push 2` and `push 1` on stack and then pop them and placing them at appropriate index starting from start. – Ahtisham Nov 16 '17 at 18:35
  • you could use stack to push the elements in it and pop them. eg: `arr db 3, 2, 1` `push 3`, `push 2` and `push 1` on stack and then pop them and placing them at appropriate index. – Ahtisham Nov 16 '17 at 19:05

4 Answers4

2

I am not really good in assembly so there might exist a better answer (this one works).

TITLE Reversing an array without using oneother array
INCLUDE Irvine32.inc

.data
    array1 DWORD 10d,20d,30d,40d,50d,60d,70d,80d,90d
.code
main PROC
        mov ESI, OFFSET array1  ;ESI now points to the first item of array1
        mov EDI, SIZEOF array1
        add EDI, OFFSET array1
        sub EDI, TYPE array1    ;EDI now points to the last item of array1

        mov ECX, LENGTHOF array1
        shr ECX, 1          ;now ecx is half the length of the array1
L1:     mov EAX, [ESI]          ;in this loop we reverse the items of the array
        mov EBX, [EDI]
        mov [EDI],EAX
        mov [ESI],EBX
        add ESI, TYPE array1
        sub EDI, TYPE array1
        LOOP L1

        mov ECX, LENGTHOF array1;here we just print the array
        mov ESI, OFFSET array1
L2:     MOV EAX, [ESI]
        call WriteInt
        call Crlf
        add ESI, TYPE array1
        LOOP L2
        exit        
main ENDP
END main
captain monk
  • 719
  • 4
  • 11
  • 34
  • Yes, except you don't need [the slow `loop` instruction](https://stackoverflow.com/questions/35742570/why-is-the-loop-instruction-slow-couldnt-intel-have-implemented-it-efficiently). Just `cmp esi, edi` / `jb L1` to loop while the start pointer is below the end pointer. The pointer setup can be simpler, too: either put a label at the end of the array, or `mov edi, OFFSET array1 + SIZEOF array1 - TYPE array1` to do all that calculation at assemble type. – Peter Cordes Nov 14 '17 at 18:51
2

Well, point the begin of the array with esi and the end with edi, load the two.. Elements (?), swap them then change esi and edi accordingly and repeat until.... hint: you don't have to swap anything, since you're in assembly =P

BlackBear
  • 22,411
  • 10
  • 48
  • 86
  • dunno who down voted ya. Upvote from me to counteract it.Thanks for answering! – darko Mar 10 '11 at 22:08
  • I know this is very far fetched but can you explain the last part? "you don't have to swap anything, since you're in assembly" – cptalpdeniz Oct 17 '22 at 03:22
-1

A pro would use the special string-instructions and source- and destination-registers; but that would probably look like you cheated your homework.

The following are basic memonics you can use to achieve your goal:

  • MOV destination source

    MOV eax,array loads the address of array into eax

    MOV edx,[eax] loads the value that is pointed to by eax into edx

  • INC eax increases the value in eax by one

  • OR eax, eax (this sets the zero-flag if eax is zero)

  • JZ label (jumps to label if zero-flag is set)

A label is set by adding a colon ":" like label:

Bernd Elkemann
  • 23,242
  • 4
  • 37
  • 66
  • With *special string-instructions* are you referring to movs*? I heard they're obsolete – BlackBear Mar 09 '11 at 21:14
  • 1
    Obsolete as in possibly wreaks havoc in modern pipelines, but still make elegant and simple solutions. – Jens Björnhager Mar 10 '11 at 11:51
  • not talking about MOVS. talking about **microcode** using R/ESX and R/EDX. besides: that is not at all what the question or my answer are about. – Bernd Elkemann Mar 10 '11 at 12:07
  • @eznme, dunno who down voted ya. Upvote from me to counteract it.Thanks for answering! – darko Mar 10 '11 at 22:07
  • A pro would use 4-byte loads and `bswap` to reverse 4 bytes in a register. You might consider `lodsd` for one of the loads and pointer increments, but only on Haswell and newer where it's only 2 uops. (Same as `mov eax, [esi]` / `add esi,4`). Also, [use `test eax,eax` to check if EAX is zero; `or same,same` is worse](https://stackoverflow.com/questions/33721204/test-whether-a-register-is-zero-with-cmp-reg-0-vs-or-reg-reg/33724806#33724806). But that makes no sense because it's a pointer, not an index, in your suggested code. – Peter Cordes Oct 07 '19 at 16:58
  • Most CPUs have SSSE3 these days, and if so you can byte-reverse (or dword-reverse) 16 bytes at a time. Your answer suggests doing 4-byte loads, but also suggests `inc eax` which only advances by 1 byte. rep-string instructions aren't useful here: they all use the same direction flag but you need to read in both directions and write in both directions for an in-place reverse. Even or single `movsd` isn't useful. And `stosd` is slower than necessary. – Peter Cordes Oct 07 '19 at 16:59
-1
INCLUDE Irvine32.inc
.data
arr1 word 1,3,4,6,7,8,9
.code
main PROC
mov esi,offset arr1
mov ax,offset arr1
mov ecx,lengthof arr1-1
l1:
mov ax,type arr1
loop l1

mov ecx,lengthof arr1
l2:
mov eax,[esi]
mov ebx,[ax]
xchg eax,ebx
mov esi,eax
mov ebx,ax

add esi,type arr1
sub ax,type arr1
dec ecx
loop l2


call dumpRegs
exit 
main ENDP
END main
Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
  • 4
    While this code may solve the question, [including an explanation](//meta.stackexchange.com/q/114762) of how and why this solves the problem would really help to improve the quality of your post, and probably result in more up-votes. Remember that you are answering the question for readers in the future, not just the person asking now. Please [edit] your answer to add explanations and give an indication of what limitations and assumptions apply. – Suraj Rao Oct 07 '19 at 16:46
  • 1
    `mov ebx,[ax]` won't assemble; 16-bit addressing modes can't use `AX` as a base or index. And this is 32-bit code so you'd almost certainly fault if you used a valid register but still truncated a 32-bit label address to 16-bit. Plus this doesn't have any store instructions in either loop, just a useless `xchg` and reg-reg moves. And a super-weird `dec ecx` / `loop` instead of using `length / 2` as the count in the first place, or walking 2 pointers until they cross like a normal person. I downvoted this just for inefficiency (and lack of explanation) before noticing it was totally broken! – Peter Cordes Oct 07 '19 at 16:54