Hi! Welcome to the seventh chapter of this series. Wow! You're kinda patient guy! Usually assembly learners gave up at the first three chapters. They cannot see any results printed on screen. This involves a lot of instructions. The style I'm using so far is to cover a few instructions step by step, refering to the higher-level programming language styles. I admit that it is hard to imagine every execution just in mind. Those impatient ones may want to go for a debugger like Turbo Debugger and stuffs to directly review the effect of each instruction executed. But hey, you're here! Alright, enough rant. Straight to the stuff.
Now, I'm going to cover loop instructions in Intel x86 assembly. Actually, there is only one loop instruction: loop. The others are just variants. This loop instruction is quite eccentric: It only recognizes the register cx as counters. No, you can't use other registers. D'oh! If you'd like to use other register, you can always employ conditional branches I covered last chapter. Nested loop is possible, but that will involve swapping registers and so forth, which is quite tedious. So, today I will only explain about plain vanilla loop.
Syntactically, loop instruction resembles jump instruction: loop somelabel. Typically, the label is somewhere up there. Look at the following example:
: mov cx, 100 ; set the counter mylabel: : : ; repeated instructions here : loop mylabel
As you observe, this structure is just like do..while construct in C/C++/Java, or like inverted repeat...until in Pascal. But here is the difference: when the processor takes loop instruction, it will first decrease the register CX by one. After that, CX is tested whether it is zero or not. If it is not zero, then jump to mylabel. So, it's kinda countdown counter. No, you can't modify this behavior. If you are dissatisfied with this, you can always use conditional branches instead. But trust me, this construct is a bit faster than the usual branches. Therefore, I encourage you to transform your loop to conform with this norm. (Pardon the pun) :-)
Well, there is no restrictions on where the label is located, actually. You can place the label way down if you'd like to. This may not make sense because in that way, nothing gets repeated. Unless, some assembly wizards get some tricks to perform their arcane "sorcery".
Let's take 1+2+...+10 example from the last chapter. We'll transform it to using loop instruction. The next snippets will show you how. Woow.... that's pretty short, right?
ideal p286n model tiny codeseg org 100h jmp start start: mov cx, 10 ; The counter is in CX mov ax, 0 ; I use AX as a sum holder myloop: add ax, cx ; ax = ax + cx loop myloop quit: ; here ax will hold the value of 1+2+...+10 mov ax, 4c00h int 21h end
In MASM version:
.286 .model tiny .code org 100h entry: jmp start ; your data and subroutine here start: mov cx, 10 ; The counter is in CX mov ax, 0 ; I use AX as a sum holder myloop: add ax, cx ; ax = ax + cx loop myloop quit: ; here ax will hold the value of 1+2+...+10 mov ax, 4c00h int 21h end entry
You have probably seen the instructions loopz or loopnz in a source code. What does it mean? It is just like loop except that before deciding whether to jump or not, the processor also look for the zero flag. In loopz, if CX is not 0 and the zero flag is set (i.e. equals to 1), then it takes the jump. The loopnz is on the contrary: If CX is not 0 and zero flag is reset (i.e. equals to 0), then it takes the jump. FYI, loopz is an acronym for "loop while zero", whereas loopnz is "loop while not zero". I don't want to discuss them further here as it will involves more knowledge in assembly. So, you'd better practice on the basic loop instruction first.
OK, I think that's all for now. See you next time.
Chapter 8
News Page
x86 Assembly Lesson 1 index
Contacting Me
Roby Joehanes © 2001