Condition: jumps if SF = 0, meaning the top bit of the last result (bit 7 or bit 15) is clear. For signed numbers that is "zero or positive". The classic use is an absolute value, where the negation is skipped when the number is already non-negative:
MOV AL, -7TEST AL, AL ; MOV set no flags; TEST doesJNS POS1 ; already >= 0NEG AL ; -7 -> 7POS1:ADD AL, "0" ; digit -> characterMOV DL, ALMOV AH, 02h ; DOS: print the character in DLINT 21h
One value has no positive twin: NEG of 80h (−128) gives 80h again, still negative, with OF = 1. A loop counting down with DEC SI / JNS TOP1 runs for SI = n, n − 1, ..., 0 and stops when SI becomes −1, which is a handy way to walk an array backwards including element 0 (as long as n is below 8000h).
Range
On the 8086 JNS exists only in the SHORT form: two bytes, opcode 79h and a signed 8-bit displacement counted from the end of the instruction. The target must lie within −128..+127 bytes of that point. To go farther, invert the test and hop over an unconditional JMP, which can reach the whole segment. MASM 6 makes this rewrite itself when it finds the target out of range (its default OPTION LJMP), so the listing may show two instructions where you wrote one.
JS SKIP1 ; the opposite test, a short hopJMP FARAWAY ; any distance in the segmentSKIP1:
Later CPUs
The 80386 added a near form of every conditional jump, 0Fh 89h followed by a 16-bit displacement (32-bit in 32-bit code), so from the 386 on JNS can reach anywhere in the segment. Code for the 8086 must stay with the short form.