I have been studying on my lonesome, in hopes of becoming more in touch with assembly, and feel that I have been doing pretty well so far.
However, I do have a few questions, including:
- What is the major/minor differences between a signed, and unsigned number? When do I need to worry about this?
- When would I use mul over imul or vice versa?
- When would I use div over idiv or vice versa?
- Why in binary addition, does 1 + 1 equal 0 with a carry and not 1 with a carry?
- In assembly programming in general, what are the major differences between protected, and unprotected?
- Is there anytime, you would use one mode over another?
What is the major/minor differences between a signed, and unsigned number? When do I need to worry about this?
If the variable will need to hold both positive and negative numbers, you will want it to be signed. Otherwise, it can be unsigned as you won't need to store the +/- sign.
Why in binary addition, does 1 + 1 equal 0 with a carry and not 1 with a carry?
1 + 1 ----- 10
When we add 1 and 1 in binary, we encounter and overflow situation which is just fancy shmancy talk for needing to have more digits to represent any larger values. It's a bit like adding 1 and 9 in decimal: we have to overflow into the tens column, thus giving the result of
10. Our result is 0 and we have to carry the one.
The same principle applies in binary, except that we don't count up to 9 and then overflow into the 10s column. Instead, we overflow into the twos column, then after we've reached 11, we overflow into the 4s column and so on.
1 + 1 = carry & 1 simply because
1 + 1 = 10. Does that explain it? :)
The X86 processor has two fundemantal modes, Real & Protected. There are 4 other modes derived from these and unreal or as you put it unprotected is one, or maybe you meant real mode. At this point in time and assuming you're very novice I wouldn't delve into this too deep unless you are already designing your own operating system.
I do my development work on an Intel Q6600 using Ubuntu 12.10 using only operating systems API's. So here is an example of my implementation of a procedure that reads a string of characters from the console.
STDIN equ 0 SYS_READ equ 0 LF equ 10 global GetS section .text ; ============================================================================================= ; ENTER: RCX = Maximum characters ; RDI = Pointer to buffer ; LEAVE: RAX = Number of characters entered ; RAX = Negative value if overflow (ABS value is characters entered). ; RCX = Remaining space availiable in buffer ; RDI = Next available postion if RCX. ; FLAGS: ZF = 0 Valid entry ; ZF = 1 NULL entry ; SF = 1 Overflow (caller should do something to waste input stream) ; --------------------------------------------------------------------------------------------- GetS push rsi push rdx ; Setup for kernel push rcx pop rdx ; ARG3 = Maximum characters push rdi pop rsi ; ARG2 = Pointer to input buffer xor eax, eax ; ARG0 = Sys_Read mov edi, eax ; ARG1 = STDIN syscall ; Determine next position and update space left in buffer. Replace CR with NULL. sub edx, eax ; Decrement space left. push rdx pop rcx ; Update return value dec eax push rax mov rdi, rsi add rdi, rax ; RDI = Pointer to EOS mov al, 0 cmp byte [rdi], LF ; Replace LF with NULL jz .Done ; Buffer was overrun. Don't post NULL as it may overwrite adjacent data ; Probably should do something here like cin.ignore (100, '\n'). inc rdi ; Bump to next position anyway pop rax neg rax jmp .Exit ; Replace LF as last character with NULL .Done stosb pop rax ; Retrieve initial size or eax, eax ; Set flags .Exit pop rdx pop rsi ret
This page on X86 instructions would be a really good reference for you as those used most often are listed first. Get to know them intrinsically first as once you start getting into GUI development possibly you don't want to have too many sources confusing the issue in debugging.