Can't figure out how to fix "Invalid mix of operators and operands" error in assembly
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
ECX is the address of the text to put onto the screen. (An address is roughly the same as a pointer in C). If ECX does not hold an address or that address does not point to text, then it won't work.
The stream << operator in C++ and many print functions in other languages are smart about the type of information you give them. For almost any type, they do output formatting appropriate to that type. The Linux system call you are using does not do any of that. It can handle a pointer to characters. If those characters are readable text, you'll get readable results. Otherwise not.
Quote:
Also, if the above is true, then this would fix some of the other errors, too, as well?
Code:
mov ecx, [num] ;<-------Also here
This feels like you're just doing guess and check of your asm code through the forum. Guess and check is a pretty lame approach to programming when you test it yourself with quick turn around. When you ask us to re explain what is wrong with each guess, you're getting nowhere.
I'm glad to answer reasonable questions, but first try to understand what has already been said and try to put some thought rather than guesswork into the purpose of each asm instruction in your code.
ECX is the address of the text to put onto the screen. (An address is roughly the same as a pointer in C). If ECX does not hold an address or that address does not point to text, then it won't work.
That's what I meant, really...
Quote:
This feels like you're just doing guess and check of your asm code through the forum. Guess and check is a pretty lame approach to programming when you test it yourself with quick turn around. When you ask us to re explain what is wrong with each guess, you're getting nowhere.
I'm glad to answer reasonable questions, but first try to understand what has already been said and try to put some thought rather than guesswork into the purpose of each asm instruction in your code.
Alright then. How about I put a few hours of writing and re-writing into this code, and if it doesn't work, I'll come back here, after I re-read all of the other posts? Will that help? It's just the way I learn new things, I ask questions about what's "right" and whats "wrong" for a particular situation and modify what I have accordingly, sometimes that means guesswork. You have to remember, I've only played around with higher level languages. I was good at Python for a time, but I've completely forgotten all of that. And I've only been learning asm for about a week now.
mov eax, 4
mov ebx, 1
mov ecx, [num] ;<-------Also here
inc [ecx] ;<-------And here
mov edx, numL
int 80h
If you can tell me why you think ecx would contain a valid address when you've done the above and if it did contain an address why you think there is text at that address, then I could know what is confusing you and give more targeted help.
But if I don't know what you think is accomplished by the two lines above that involve ecx, then I can't tell you anything more informative than "wrong".
But if I don't know what you think is accomplished by the two lines above that involve ecx, then I can't tell you anything more informative than "wrong".
Alright then, I'll tell you what I think is happening.
What I *think* is happening is that I move the contents of num to ecx with
Code:
mov ecx, [num]
and then I increment of contents of ecx by one using
Code:
inc [ecx]
Happy? Sorry if I sound angry, I've just had a rough day.
Alright then, I'll tell you what I think is happening.
Ignoring the big difference between "accomplished" and "happening", I'll correct just one detail:
Quote:
and then I increment of contents of ecx by one using
Code:
inc [ecx]
No, that instruction would increment the thing pointed to by ecx (since the value in ecx is not a valid address, that instruction would seg fault). But since you didn't give the size of the thing pointed to, I think it is incorrect even at assembly time.
Register name don't act the same as addresses: inc num is incorrect because num is an address and can't be incremented. inc byte [num] increments the byte at address num inc ecx increments the contents of the 32 bit register ecx inc byte [ecx] increments the byte in memory pointed to by ecx.
Alright, I understand that now. Now I've got one more question: I've taken into consideration everything I've learned here, and wrote a working script, but it doesn't do exactly what intend it to do. after compiling/linking, I run the script and it just prints out "" (minus the quotes), but I wrote it to where (at least that's how I think I wrote it) to print out the contents of "esi". Here is the script in question:
Code:
;Loop from 2-10 + print ":D"
global _start
_start:
section .data
m: db ":D",10
mL: equ $ - m
section .text
mov esi, 1
jmp while
loop1:
cmp esi, 10
jne while
jng exit
while:
inc esi
mov eax, 4
mov ebx, 1
mov ecx, esi
mov edx, 5
int 80h
jmp loop1
exit:
mov eax, 4
mov ebx, 1
mov ecx, m
mov edx, mL
int 80h
mov eax, 1
mov ebx, 0
int 80h
To make a long story short, I want to know what I am doing wrong here (it's a while statement) so that it is only printing out "", and not the numbers 2 through 10. I do hope I am not asking for too much.
steviebob, et al.
Please do not be daunted with the task of learning assembly language.
The x86 processors are not the easiest machines to use for learning assembly language. I personally started with various processors much simpler than the x86. None of the others have the complications of segmented memory addresses with corresponding segment registers and such a variety of data sizes as there are in the x86 processors. On the other hand, these other processors are not as ubiquitously available as Intel x86 architecture because the x86 is the processor family used in the common PC.
Even on simpler processors, you should not expect to learn assembly language in a few days or even in a few weeks. When you get down to the level of assembly language on a PC you are at a very low level of operation and working more or less at the level of the hardware. However, you still have operating system level services exposed by way of the software interrupts. These provide such facilities as printing a character or a string of characters on the console or getting a character or a string of characters from the keyboard.
When you write assembly language you need to understand the assembly-language level view of the CPU, which includes the program counter, main registers, stack pointer, frame pointer, and, on the x86, the segment registers. Besides this, you must understand the various addressing modes provided by the processor. Some assembly languages have more opcodes than there are keywords in some higher level languages.
I recommend that you search the web to find a tutorial that you find clear for you. It should include example code in some sort of progression of increasing levels of complexity. Make sure you understand every word in the examples. Type in (or copy and paste), assemble, link, load, and run every example.
I do not want to discourage you from asking for help on this forum or from me. My comments are only personal opinions and lessons learned from quite a while spent programming and in formal education and in no way represent the policy on this forum. I am not a moderator, just an erstwhile visitor. If you are following a tutorial and get stuck, do not pound your head against it for a week! I want you to make progress with this educational endeavor.
ECX is the address of the text to put onto the screen.
Quote:
Originally Posted by steviebob
That's what I meant, really.
ECX should be the address of the text to put onto the screen.
Quote:
Originally Posted by steviebob
I've taken into consideration everything I've learned here
ECX should be the address of the text to put onto the screen.
Quote:
Originally Posted by steviebob
Code:
mov esi, 1
...
inc esi
...
mov ecx, esi
I want to know what I am doing wrong here
ECX should be the address of the text to put onto the screen.
Sorry. I don't know another way to say it. I assume you understand that after the above three instructions ecx will hold the value 2. I assume you understand that 2 is not a valid address. I assume you also understand that you didn't include any code to convert any number into text.
I assume you also understand that you didn't include any code to convert any number into text.
Then I'll say this: I don't know how to do that. You have to remember how new I am to this, and I'm learning out of experience, which to say, I have very little with asm.
WARNING! This code is not tested. It probably has bugs.
A quick way to translate numbers to text characters is with a lookup table. Set up an array of characters using the db pseudo op. Then use a little routine which takes a four-bit digit as parameter and returns the character representing that digit as a character.
Code:
;; translate nybble in eax to character in eax
Hex2Char: push ecx ;save c register
and reg_eax,0x0000000f ;mask a to four bits
mov ecx,DigitTable ;c <- table address
add ecx,eax ;add digit offset
mov al,[byte ecx] ;a <- char from table
and reg_eax,0x000000ff ;mask a to byte
pop ecx ;restore c register
ret ;digit character in a
DigitTable: db '0123456789abcdef'
Of course this will only translate a single digit at a time. For decimal readout, you will need to convert a longer number into digits by
Code:
div eax,10
and using the remainder from the D register.
If you want hexadecimal digits, all you need to do is right shift the number four bits for each hex digit.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.