I want to make a program to pick a color in a list depending on a certain level. However, when i'm getting the value with
MOV EAX, [COLOR1 + ECX * 4]
I'm getting the error message:
Error: Command failed: timeout 7 ./HelloWorld
How can I make it work?
I know this is causing the error because if I transform it into MOV EAX, [COLOR1]
I don't get the error. I see people here on stackoverflow and elsewere doing [EAX+ECX*4] (I've tried it too). I also tried doing [COLOR1 + ECX], it didn't work but [COLOR1 + 1] Works.
I can also seperate everything like this
IMUL ECX, 4
MOV EAX, [COLOR1]
ADD EAX, ECX
Which is I think the same?
For my code in itself, my objective is if LEVEL = 0, should get the first value in COLOR1 and COLOR2 (00223AD0h and 0040B2DFh) and LEVEL = 1 the next one and so on. Btw, I'm using OneCompiler.
SECTION .DATA
COLOR1 DD 00223AD0h, 00BF2A04h, 000BA109h, 00AF04AFh, 00CB0556h, 005E90DFh, 00BF2A04h, 007703D5h,
COLOR2 DD 0040B2DFh, 00E1963Fh, 007CBD11h, 00D775D9h, 0058D590h, 0058D590h, 00707070h, 009E050Dh
LEVEL DB 0
section .text
global _start
_start:
MOV ECX, LEVEL
CALL .LOOP
MOV EAX, [COLOR1 + ECX * 4] ;Option I'm trying but doesn't work
MOV [COLOR1CUR], EAX
IMUL ECX, 4 ;Option that kinda work but the result isn't what i want
MOV EAX, [COLOR2]
ADD EAX, ECX
MOV [COLOR2CUR], EAX
CALL .PRINT
MOV EAX,1 ; The system call for exit (sys_exit)
MOV EBX,0 ; Exit with return "code" of 0 (no error)
INT 80h
.LOOP:
SUB ECX, 10
CMP ECX, 0
JL SHORT .LOOP
ADD ECX, 10
RET
.PRINT:
;MOV EAX, COLOR1CUR
;CALL CONVERT_TO_STRING ; trying to make the color readable but that's next step so not on this post
mov eax, 4 ; The system call for write (sys_write)
mov ebx, 1 ; File descriptor 1 - standard output
mov ecx, COLOR1CUR
mov edx, 16
int 80h
RET
As worked out in comments: MOV ECX, LEVEL
seems to be intended to load the value from LEVEL
into ECX
, like C ecx = level;
. But what it actually does is to put the address of LEVEL
into ECX
, like ecx = &level;
, without actually loading anything from memory at all.
Memory accesses in NASM's Intel-syntax x86 assembly language use square brackets, as you're already doing elsewhere. But MOV ECX, [LEVEL]
wouldn't be correct: since ECX
is a 32-bit register, this would perform a 32-bit load which retrieves 4 bytes from memory. But you're only using one byte to store the level (you have LEVEL DB 0
rather than LEVEL DD 0
), so the other three bytes would be whatever garbage happens to come next in memory. To load a narrower value into a wider register, you need to either zero-extend (MOVZX
) or sign-extend (MOVSX
) and specify the size of the object to be loaded. Presumably zero-extension is appropriate here, since it wouldn't ever make sense to interpret LEVEL
as a negative number, so:
MOVZX ECX, BYTE [LEVEL]