0

We can only edit bold part to find positive number from given array. This is what i have tried in visual basic and i am just getting result as zero, Can someone say where it got wrong?

int solution(const int arr[], size_t arr_size)
{
    int result = 0;
    __asm
    {
        **MOV eax, arr
        MOV edx, eax
        MOV ebx, 10
        XOR ecx, ecx
        LEA esi, size arr
        NEXT2 : 
        MOV edi, esi
                SHR edi, 10
                JNC NEXT1
                JMP NEXT3
                NEXT1 : INC ecx
                        NEXT3 : INC SI
                                DEC ebx
                                JNZ NEXT2
        MOV[result], ecx;**
    }
        return result;
}
    int main()
    {
        int result;
        int arr[] = { 0, -1, 2, -3, 4, -5, 6, -7, 8, -9 };
        result = solution(arr, sizeof(arr) / sizeof(arr[0]));
        printf("Grade 6 result = %d\n", result);
        getchar();
        return 0;
    }
martin
  • 1
  • 3
  • 2 things jump right out at me: 1) You need to understand how `MOV edx, eax` is different from (say) `MOV edx, [eax]`. Visually they may look similar, but the meaning is very different. 2) I don't believe `LEA esi, size arr` is going to give you what you want either. The size of the array was passed in `arr_size`. Why not use that? next, you should try stepping thru all this in the debugger. Look at what ends up in each of the registers (eax, ecx, etc). Lastly, you should have comments on each line of the assembler saying what (you think) they do. It makes your life (and ours) much easier. – David Wohlferd Oct 26 '17 at 02:27

1 Answers1

0

1) Here is a piece of code I use to get the size of an array:

    mov     ebx, 0              ; set ebx to zero to start checking at index 0
countloop:
    inc     ebx                 ;Increase ebx for next loop

    cmp     arr[ebx], '\0'      ;compare arr at index [ebx] to end char '\0'
    jne     countloop           ;if not equal, jump back and try for next index 

    mov     arrlength, ebx      ;if equal to '\0', load the value of ebx (actual length of the array) into the empty length variable

The reason why you look for '\0' is that the string is stored like a char array and the register only stores the first char, the loops to get the other until it get that 'end' characters. I believe other characters would get the loop to stop, not sure which one, but \0 does work

2) Then use the value stored in arrlength as the number of loops you will need to check your array and find positives.

    MOV ecx, arrlength  ; This sets the loop counter register (ECX) to the size of your array
    MOV ebx, 0          ; Set this to 0 as we will use it again as index
    MOV esi, 0          ; Same 

compareLoop:     
    MOV eax, arr[ebx]   ; load value of arr at index ebx

    CMP eax, 0          ; sets flag, comparing eax to 0

    JL  lessThan        ;JL --> jump if first operand lower than second operand

    MOV newArr[esi], eax  ;Put the value (which is >0, in a new array) 
    add esi, 4           ; To point to the next position   

lessThan:
    add   ebx, 4        ; adding for to ebx so that now it has the index of next value in array

    loop  compareLoop   ; until ecx = 0

I basically showed you how I would do it, I am far from a pro, and simply don't understand the way you proceeded.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
J.C
  • 252
  • 5
  • 18
  • Thanks! How did you do that?! – J.C Jan 04 '18 at 07:00
  • How did I edit your answer? I clicked the [edit] button. Code-formatting blocks need a blank line to start, otherwise it's just part of a paragraph. – Peter Cordes Jan 04 '18 at 07:03
  • You don't need a separate pass to find the length. Put the end-of-array check into the compare-against-zero loop. And [don't use the `loop` instruction, it's slow.](https://stackoverflow.com/questions/35742570/why-is-the-loop-instruction-slow-couldnt-intel-have-implemented-it-efficiently). Also, your first loop is incrementing the pointer by one, but you're checking dword elements in the 2nd loop (like the OP wants). So you'll have a false-positive end of the array if it contains `0x0000001, 0x10000000` for example (6 contiguous zero bytes in those 8 bytes). – Peter Cordes Jan 04 '18 at 07:06
  • It also makes no sense to use a character constant instead of just testing for zero. Either compare against integer zero, or `test eax,eax` to set flags the same way, because zero is special. https://stackoverflow.com/questions/33721204/test-whether-a-register-is-zero-with-cmp-reg-0-vs-or-reg-reg/33724806#33724806. (There's a special `ZF` flag which is set when a result is zero.) – Peter Cordes Jan 04 '18 at 07:07
  • Also, you get the array size as a function arg, you don't have to search for it like an implicit-length C string. (`strlen`). The OP's array doesn't end with a sentinel zero. Just remove that whole first section of your answer. – Peter Cordes Jan 04 '18 at 07:11
  • Not sure I understand what you mean about the CMP phase. Why should'nt I use 0 as second operand? Is 'TEST' setting similar flags? – J.C Jan 04 '18 at 07:48
  • I'm saying that `'\0'` makes no sense vs. `0`. And re: `test`: if you have a memory operand, `cmp dword arr[ebx], 0` is your only single-instruction option. (not counting `scasd`). But if you have the value in a register, [`cmp eax, 0` sets flags identically to `test eax,eax`](https://stackoverflow.com/questions/33721204/test-whether-a-register-is-zero-with-cmp-reg-0-vs-or-reg-reg/33724806#33724806), so `test` is slightly better (because it's shorter and old Core2 CPUs can run test/jl more efficiently than cmp/jl in 32-bit mode). – Peter Cordes Jan 04 '18 at 08:12