Which register does jnz check
Categories:
Understanding the 'jnz' Instruction in x86 Assembly
Explore the 'jnz' (jump if not zero) instruction in x86 assembly, its functionality, and how it interacts with the CPU's FLAGS register to control program flow.
In x86 assembly language, conditional jump instructions are fundamental for implementing control flow, allowing programs to make decisions and execute different code paths based on the results of previous operations. One such crucial instruction is jnz
, which stands for "jump if not zero." Understanding which CPU register jnz
checks is key to effectively using it in your assembly programs.
The Role of the FLAGS Register
The jnz
instruction, like many other conditional jump instructions in x86 assembly, does not directly check the value of a general-purpose register (like EAX
, EBX
, etc.). Instead, it inspects a specific bit within the CPU's FLAGS register (also known as EFLAGS
or RFLAGS
in 64-bit systems). This register is a collection of single-bit flags that reflect the status of the CPU after arithmetic and logical operations.
Specifically, jnz
checks the Zero Flag (ZF). The Zero Flag is set (to 1) if the result of an operation is zero, and it is cleared (to 0) if the result is non-zero. The jnz
instruction will cause a jump to the specified target address if the Zero Flag is cleared (ZF = 0), meaning the result of the preceding operation was not zero.
flowchart TD A[Previous Operation] --> B{Result is Zero?} B -- Yes (ZF=1) --> C[Do NOT Jump] B -- No (ZF=0) --> D[Jump to Target]
How the Zero Flag (ZF) influences the JNZ instruction
Operations That Affect the Zero Flag
Many x86 instructions implicitly or explicitly modify the FLAGS register, including the Zero Flag. Common instructions that affect ZF and are often followed by jnz
include:
- Arithmetic Instructions:
ADD
,SUB
,INC
,DEC
,MUL
,DIV
(results of these operations set or clear ZF). - Logical Instructions:
AND
,OR
,XOR
,TEST
(these instructions perform bitwise operations and set flags based on the result). - Comparison Instructions:
CMP
(this instruction performs a subtraction but discards the result, only setting the flags based on the comparison).
It's crucial to remember that not all instructions affect the flags. For example, MOV
instructions typically do not modify the FLAGS register.
section .data
msg db "Value is not zero!", 0xA, 0xD
len equ $ - msg
section .text
global _start
_start:
mov eax, 10 ; EAX = 10
sub eax, 10 ; EAX = 0. ZF is set (1).
jnz skip_print ; ZF is 1, so jnz does NOT jump.
; This code will execute because ZF was set by 'sub eax, 10'
mov edx, len
mov ecx, msg
mov ebx, 1
mov eax, 4
int 0x80 ; Print "Value is not zero!"
skip_print:
mov eax, 10 ; EAX = 10
sub eax, 5 ; EAX = 5. ZF is cleared (0).
jnz print_again ; ZF is 0, so jnz WILL jump.
; This code will NOT execute
mov eax, 1
int 0x80
print_again:
; This code will execute because ZF was cleared by 'sub eax, 5'
mov edx, len
mov ecx, msg
mov ebx, 1
mov eax, 4
int 0x80 ; Print "Value is not zero!" again
mov eax, 1
int 0x80 ; Exit
Example demonstrating jnz
behavior based on Zero Flag
Common Use Cases for JNZ
jnz
is frequently used in loops and conditional statements. For instance, it can be used to iterate until a counter reaches zero, or to check if a function returned a non-zero error code. A common pattern involves using DEC
to decrement a counter and then jnz
to loop if the counter is not yet zero.
section .text
global _start
_start:
mov ecx, 5 ; Initialize loop counter
loop_start:
; Do some work here
; ...
dec ecx ; Decrement counter. This affects ZF.
jnz loop_start ; If ECX is not zero (ZF=0), jump back to loop_start.
; Loop finishes when ECX becomes zero
mov eax, 1
int 0x80
Using DEC
and JNZ
for a simple loop
jnz
checks the Zero Flag, its counterpart jz
(jump if zero) jumps if the Zero Flag is set (ZF = 1). These two instructions are complementary for branching based on whether a result is zero or non-zero.