I am referring a book on Assembly Language on LInux. It recommends us to use a "io.mac" and "io.o" file for complex input output procedure(in fact, every book I came across, pushed a io.o file to use it to reduce the complexicity. This upsets me. When I am already ready to bang my head to learn the most complex low level language, why there is a need to hide any more details.
If you're goal is to learn assembly, then you should be focusing on learning the instructions, coding procedures and building various algorithms to help refine your understanding of the low level coding. The reason most people get detoured from assembly early on is because you can't
just learn assembly. From the second that you want to display the results of data movements or calculations, you immediately have to become familiar with intricate components of whatever operating system you're using. And what's worse, each operating system does things different, so that part of the code is useless when you move between various operating systems (and sometimes between different versions of the operating system).
What this guy has done is to wrap the operating system specific stuff in macros so the learner can focus on assembly without having to deal with system specific things.
I don't exactly agree with the way he's done it. To be honest, the easiest method would be to teach the students assembly, and early on in the course provide them with the details of using calls to external procedures provided by a portable language (like C).
I understand how PutStr works. But I do not understand how this GetInt Works. Wait a minute I think I guessed how this GetInt works. There is no call instruction before GetInt which means it must be a Macro.
Yep, sure is.
Let me look up there. Then, What this means
%macro PutInt 1
It literally means "declare a macro of the name 'PutInt' that takes 1 argument".
or this
%macro GetInt 1
%ifnidni %1,AX
push AX
call proc_GetInt
mov %1,AX
pop AX
%else
call proc_GetInt
%endif
%endmacro
What we have here is a wrapper to a procedure that this guy wrote. I'll try to brake it down for ya.
%macro GetInt 1
Just like in the previous, we are declaring a macro named "GetInt" that takes 1 argument.
%ifnidni %1,AX
This looks more complex than it really is... NASM uses a % followed by a number to identify which macro argument it's referencing. The %ifnidni directive compares two identifiers against each other (ignoring case) and executes the following block of code if the two identifiers are not the same.
push AX
call proc_GetInt
mov %1,AX
pop AX
If the %ifnidni line finds that the argument passed to 'GetInt' was
NOT the AX register, we must preserve the value of AX, call the procedure 'proc_GetInt' which returns with the integer in AX, store that integer in the memory location or register that was passed as the parameter to 'GetInt', and finally restore the AX register in case the code that called the macro had something valuable in AX.
%else
call proc_GetInt
%endif
This part is an alternate compilation. If the argument to 'GetInt' actually was the AX register, then we don't have to do anything except call the procedure 'proc_GetInt', and since it returns the integer in AX, you're register is already updated.
%endmacro
This line specifies that we are done declaring our 'GetInt' macro.
That's all I want to know. I have a very bad habit. I want to code everything without any io.o . I mean when I say that I can code in assembly, then I should really be able to do that. After 10 years, I do not wish to seek help of a io.o to do simplest thing. It hurts the programmer in me.
You should get out of that habit because it's a very unrealistic goal. There are very few chances in a programmers life where he can do just "pure assembly". Usually that's when you're writing framework code that'll be used by others who will deal with the system specific issues. If you code on a computer, you're going to use other peoples code, you should get used too it. Think about it, say you stop using io.o, you'll still be using the operating systems API. If you get away from the operating systems API, then you're still using the BIOS API. It's an almost never-ending cycle which only prevents you from getting any real work done.
In fact, about the only way you can write code that isn't backed by someone else's API is if you break out Verilog/VHDL and design yourself a custom CPU then get a company to print you an ASIC and code exclusively for that system. That'd be a waste of time if you ask me..