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:

Prints 7. Start with 3 and it prints 3.
MOV AL, -7
TEST AL, AL ; MOV set no flags; TEST does
JNS POS1 ; already >= 0
NEG AL ; -7 -> 7
POS1:
ADD AL, "0" ; digit -> character
MOV DL, AL
MOV AH, 02h ; DOS: print the character in DL
INT 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 hop
JMP FARAWAY ; any distance in the segment
SKIP1:

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.