Skip to content

Instantly share code, notes, and snippets.

@seiren-naru-shirayuri
Last active March 6, 2022 07:28
Show Gist options
  • Save seiren-naru-shirayuri/ee4095166699392c1e494838a7c07466 to your computer and use it in GitHub Desktop.
Save seiren-naru-shirayuri/ee4095166699392c1e494838a7c07466 to your computer and use it in GitHub Desktop.
QWORD arithmetic and comparison operations in x86 assembly
!QWORDOperations

QWORD arithmetic and comparison operations in x86 assembly.

This gist is released under GLWTPL.

#ifdef _WIN64
#error 64-bit code generation not supported
#endif
#pragma comment (lib, "legacy_stdio_definitions.lib")
extern "C" int __cdecl main1();
int main()
{
return main1();
}
title QWORD operations test
.686
.model flat, c
option casemap:none
include qwordops.inc
scanf proto c, format:ptr byte, args:vararg
printf proto c, format:ptr byte, args:vararg
.data?
a qword ?
b qword ?
c1 dword ?
.const
inputprompt byte "Enter two unsigned long longs and a int: ", 0
inputfmt byte "%llu %llu %u", 0
outputfmt byte "a(unsigned) = %llu b(unsigned) = %llu", 0ah, "a(signed) = %lld b(signed) = %lld", 0ah, "a(hex) = %#018llX b(hex) = %#018llX", 0ah, "c(unsigned) = %u", 0ah, "c(hex) = %#010X", 0ah, 0ah, 0
negfmt byte "neg: -(%lld) = %lld", 0ah, 0
addfmt byte "add: %llu + %llu = %llu", 0ah, 0
iaddfmt byte "iadd: %lld + %lld = %lld", 0ah, 0
subfmt byte "sub: %llu - %llu = %llu", 0ah, 0
isubfmt byte "isub: %lld - %lld = %lld", 0ah, 0
mulfmt byte "mul: %llu * %llu = %llu", 0ah, 0
imulfmt byte "imul: %lld * %lld = %lld", 0ah, 0
divfmt byte "div: %llu / %llu = %llu", 0ah, 0
idivfmt byte "idiv: %lld / %lld = %lld", 0ah, 0
modfmt byte "mod: %llu %% %llu = %llu", 0ah, 0
imodfmt byte "imod: %lld %% %lld = %lld", 0ah, 0
notfmt byte "not: ~%#018llX = %#018llX", 0ah, 0
andfmt byte "and: %#018llX & %#018llX = %#018llX", 0ah, 0
orfmt byte "or: %#018llX | %#018llX = %#018llX", 0ah, 0
xorfmt byte "xor: %#018llX ^ %#018llX = %#018llX", 0ah, 0
shlfmt byte "shl: %#018llX << %#04X = %#018llX", 0ah, 0
salfmt byte "sal: %#018llX << %#04X = %#018llX", 0ah, 0
shrfmt byte "shr: %#018llX >> %#04X = %#018llX", 0ah, 0
sarfmt byte "sar: %#018llX >> %#04X = %#018llX", 0ah, 0
equfmt byte "equ: %llu == %llu = %d", 0ah, 0
iequfmt byte "iequ: %lld == %lld = %d", 0ah, 0
neqfmt byte "neq: %llu != %llu = %d", 0ah, 0
ineqfmt byte "ineq: %lld != %lld = %d", 0ah, 0
lesfmt byte "les: %llu < %llu = %d", 0ah, 0
ilesfmt byte "iles: %lld < %lld = %d", 0ah, 0
gtrfmt byte "gtr: %llu > %llu = %d", 0ah, 0
igtrfmt byte "igtr: %lld > %lld = %d", 0ah, 0
leqfmt byte "leq: %llu <= %llu = %d", 0ah, 0
ileqfmt byte "ileq: %lld <= %lld = %d", 0ah, 0
geqfmt byte "geq: %llu >= %llu = %d", 0ah, 0
igeqfmt byte "igeq: %lld >= %lld = %d", 0ah, 0
.code
main1 proc c
invoke printf, addr inputprompt
invoke scanf, addr inputfmt, addr a, addr b, addr c1
invoke printf, addr outputfmt, a, b, a, b, a, b, c1, c1
invoke negq, a
invoke printf, addr negfmt, a, eax, edx
invoke addq, a, b
invoke printf, addr addfmt, a, b, eax, edx
invoke addq, a, b
invoke printf, addr iaddfmt, a, b, eax, edx
invoke subq, a, b
invoke printf, addr subfmt, a, b, eax, edx
invoke subq, a, b
invoke printf, addr isubfmt, a, b, eax, edx
invoke mulq, a, b
invoke printf, addr mulfmt, a, b, eax, edx
invoke imulq, a, b
invoke printf, addr imulfmt, a, b, eax, edx
invoke divq, a, b
invoke printf, addr divfmt, a, b, eax, edx
invoke idivq, a, b
invoke printf, addr idivfmt, a, b, eax, edx
invoke modq, a, b
invoke printf, addr modfmt, a, b, eax, edx
invoke imodq, a, b
invoke printf, addr imodfmt, a, b, eax, edx
invoke notq, a
invoke printf, addr notfmt, a, eax, edx
invoke andq, a, b
invoke printf, addr andfmt, a, b, eax, edx
invoke orq, a, b
invoke printf, addr orfmt, a, b, eax, edx
invoke xorq, a, b
invoke printf, addr xorfmt, a, b, eax, edx
invoke shlq, a, c1
invoke printf, addr shlfmt, a, c1, eax, edx, a, c1, eax, edx
invoke shlq, a, c1
invoke printf, addr salfmt, a, c1, eax, edx, a, c1, eax, edx
invoke shrq, a, c1
invoke printf, addr shrfmt, a, c1, eax, edx, a, c1, eax, edx
invoke sarq, a, c1
invoke printf, addr sarfmt, a, c1, eax, edx, a, c1, eax, edx
invoke equq, a, b
invoke printf, addr equfmt, a, b, eax
invoke equq, a, b
invoke printf, addr iequfmt, a, b, eax
invoke neqq, a, b
invoke printf, addr neqfmt, a, b, eax
invoke neqq, a, b
invoke printf, addr ineqfmt, a, b, eax
invoke lesq, a, b
invoke printf, addr lesfmt, a, b, eax
invoke ilesq, a, b
invoke printf, addr ilesfmt, a, b, eax
invoke gtrq, a, b
invoke printf, addr gtrfmt, a, b, eax
invoke igtrq, a, b
invoke printf, addr igtrfmt, a, b, eax
invoke leqq, a, b
invoke printf, addr leqfmt, a, b, eax
invoke ileqq, a, b
invoke printf, addr ileqfmt, a, b, eax
invoke geqq, a, b
invoke printf, addr geqfmt, a, b, eax
invoke igeqq, a, b
invoke printf, addr igeqfmt, a, b, eax
xor eax, eax
ret
main1 endp
end
.686
.model flat, c
option casemap:none
include qwordops.inc
.code
;Calculate signed 64-bit negation (-a)
;long long __cdecl negq(long long a)
negq proc, a:sqword
mov eax, dword ptr [a]
mov edx, dword ptr [a+4]
neg eax
adc edx, 0
neg edx
ret
negq endp
;Calculate 64-bit addition (a + b)
;unsigned long long __cdecl addq(unsigned long long a, unsigned long long b)
;long long __cdecl addq(long long a, long long b)
addq proc, a:qword, b:qword
mov eax, dword ptr [a]
add eax, dword ptr [b]
mov edx, dword ptr [a+4]
adc edx, dword ptr [b+4]
ret
addq endp
;Calculate 64-bit substraction (a - b)
;unsigned long long __cdecl subq(unsigned long long a, unsigned long long b)
;long long __cdecl subq(long long a, long long b)
subq proc, a:qword, b:qword
mov eax, dword ptr [a]
sub eax, dword ptr [b]
mov edx, dword ptr [a+4]
sbb edx, dword ptr [b+4]
ret
subq endp
;Calculate unsigned 64-bit multiplication (a * b)
;unsigned long long __cdecl mulq(unsigned long long a, unsigned long long b)
mulq proc uses ebx, a:qword, b:qword
mov eax, dword ptr [a]
mul dword ptr [b]
mov ebx, eax
mov ecx, edx
mov eax, dword ptr [a+4]
mul dword ptr [b]
add ecx, eax
mov eax, dword ptr [a]
mul dword ptr [b+4]
add ecx, eax
mov eax, ebx
mov edx, ecx
ret
mulq endp
;Calculate signed 64-bit multiplication (a * b)
;long long __cdecl imulq(long long a, long long b)
imulq proc uses ebx, a:sqword, b:sqword
mov ebx, dword ptr [a+4]
xor ebx, dword ptr [b+4]
.if sdword ptr [a+4] < 0
neg dword ptr [a]
adc dword ptr [a+4], 0
neg dword ptr [a+4]
.endif
.if sdword ptr [b+4] < 0
neg dword ptr [b]
adc dword ptr [b+4], 0
neg dword ptr [b+4]
.endif
invoke mulq, qword ptr a, qword ptr b
test ebx, ebx
.if sign?
neg eax
adc edx, 0
neg edx
ret
.else
ret
.endif
imulq endp
;Calculate unsigned 64-bit division (a / b)
;unsigned long long __cdecl divq(unsigned long long a, unsigned long long b)
divq proc, a:qword, b:qword
;If high dword of b isn't equal to 0, do binary long division.
.if dword ptr [b+4] != 0
push esi
push edi
push ebx
mov ebx, dword ptr [a] ;ebx = LODWORD(dividend)
mov esi, dword ptr [a+4] ;edi:esi = remainder. initial value is high dword of dividend
xor edi, edi
xor eax, eax ;edx:eax = quotient
xor edx, edx
mov ecx, 32 ;ecx = i
l1: ;while (i != 0) {
dec ecx
bt ebx, ecx ;CF = (LODWORD(dividend))[i - 1];
rcl esi, 1 ;remainder << 1, remainder[0] = CF;
rcl edi, 1
cmp edi, dword ptr [b+4] ;if remainder >= divisor {
ja l2
jb l3
cmp esi, dword ptr [b]
jb l3
l2:
sub esi, dword ptr [b] ;remainder -= divisor;
sbb edi, dword ptr [b+4]
bts eax, ecx ;(LODWORD(quotient))[i - 1] = 1; }
l3:
inc ecx
loop l1 ;--i; }
pop ebx
pop edi
pop esi
ret
;Else do base 4294967296 long division.
.else
mov eax, dword ptr [a+4]
xor edx, edx
div dword ptr [b]
mov ecx, eax
mov eax, dword ptr [a]
div dword ptr [b]
mov edx, ecx
ret
.endif
divq endp
;Calculate singed 64-bit division (a / b)
;long long __cdecl idivq(long long a, long long b)
idivq proc uses ebx, a:sqword, b:sqword
mov ebx, dword ptr [a+4]
xor ebx, dword ptr [b+4]
.if sdword ptr [a+4] < 0
neg dword ptr [a]
adc dword ptr [a+4], 0
neg dword ptr [a+4]
.endif
.if sdword ptr [b+4] < 0
neg dword ptr [b]
adc dword ptr [b+4], 0
neg dword ptr [b+4]
.endif
invoke divq, qword ptr a, qword ptr b
test ebx, ebx
.if sign?
neg eax
adc edx, 0
neg edx
ret
.else
ret
.endif
idivq endp
;Calculate unsigned 64-bit modulo (a % b)
;unsigned long long __cdecl modq(unsigned long long a, unsigned long long b)
modq proc, a:qword, b:qword
;If high dword of b isn't equal to 0, do binary long division.
.if dword ptr [b+4] != 0
push ebx
mov ebx, dword ptr [a] ;ebx = LODWORD(dividend)
mov eax, dword ptr [a+4] ;edx:eax = remainder. initial value is high dword of dividend
xor edx, edx
mov ecx, 32 ;ecx = i
l1: ;while (i != 0) {
dec ecx
bt ebx, ecx ;CF = (LODWORD(dividend))[i - 1];
rcl eax, 1 ;remainder << 1; remainder[0] = CF;
rcl edx, 1
cmp edx, dword ptr [b+4] ;if remainder >= divisor {
ja l2
jb l3
cmp eax, dword ptr [b]
jb l3
l2:
sub eax, dword ptr [b] ;remainder -= divisor; }
sbb edx, dword ptr [b+4]
l3:
inc ecx
loop l1 ;--i; }
pop ebx
ret
;Else do base 4294967296 long division.
.else
mov eax, dword ptr [a+4]
xor edx, edx
div dword ptr [b]
mov eax, dword ptr [a]
div dword ptr [b]
mov eax, edx
xor edx, edx
ret
.endif
modq endp
;Calculate signed 64-bit modulo (a % b)
;long long __cdecl imodq(long long a, long long b)
imodq proc, a:sqword, b:sqword
.if sdword ptr [a+4] < 0
neg dword ptr [a]
adc dword ptr [a+4], 0
neg dword ptr [a+4]
.endif
.if sdword ptr [b+4] < 0
neg dword ptr [b]
adc dword ptr [b+4], 0
neg dword ptr [b+4]
.endif
invoke modq, qword ptr a, qword ptr b
.if sdword ptr [a+4] < 0
neg eax
adc edx, 0
neg edx
ret
.else
ret
.endif
imodq endp
;Calculate 64-bit bitwise not (~a)
;unsigned long long __cdecl notq(unsigned long long a)
;long long __cdecl notq(long long a)
notq proc, a:qword
mov eax, dword ptr [a]
not eax
mov edx, dword ptr [a+4]
not edx
ret
notq endp
;Calculate 64-bit bitwise and (a & b)
;unsigned long long __cdecl andq(unsigned long long a, unsigned long long b)
;long long __cdecl andq(long long a, long long b)
andq proc, a:qword, b:qword
mov eax, dword ptr [a]
and eax, dword ptr [b]
mov edx, dword ptr [a+4]
and edx, dword ptr [b+4]
ret
andq endp
;Calculate 64-bit bitwise or (a | b)
;unsigned long long __cdecl orq(unsigned long long a, unsigned long long b)
;long long __cdecl orq(long long a, long long b)
orq proc, a:qword, b:qword
mov eax, dword ptr [a]
or eax, dword ptr [b]
mov edx, dword ptr [a+4]
or edx, dword ptr [b+4]
ret
orq endp
;Calculate 64-bit bitwise xor (a ^ b)
;unsigned long long __cdecl xorq(unsigned long long a, unsigned long long b)
;long long __cdecl xorq(long long a, long long b)
xorq proc, a:qword, b:qword
mov eax, dword ptr [a]
xor eax, dword ptr [b]
mov edx, dword ptr [a+4]
xor edx, dword ptr [b+4]
ret
xorq endp
;Calcualte 64-bit left shift (a << b)
;unsigned long long __cdecl shlq(unsigned long long a, unsigned int b)
;long long __cdecl shlq(long long a, unsigned int b)
shlq proc uses ebx, a:qword, b:dword
mov eax, dword ptr [a]
mov edx, dword ptr [a+4]
mov ecx, b
xor ebx, ebx
shld edx, eax, cl
shl eax, cl
cmp ecx, 32
cmovae edx, eax
cmovae eax, ebx
ret
shlq endp
;Calculate unsigned 64-bit logical right shift (a >> b)
;unsigned long long __cdecl shrq(unsigned long long a, unsigned int b)
shrq proc uses ebx, a:qword, b:dword
mov eax, dword ptr [a]
mov edx, dword ptr [a+4]
mov ecx, b
xor ebx, ebx
shrd eax, edx, cl
shr edx, cl
cmp ecx, 32
cmovae eax, edx
cmovae edx, ebx
ret
shrq endp
;Calculate signed 64-bit arithmetic right shift (a >> b)
;long long __cdecl sarq(long long a, unsigned int b)
sarq proc uses ebx , a:sqword, b:dword
mov eax, dword ptr [a]
mov edx, dword ptr [a+4]
mov ecx, b
mov ebx, edx
sar ebx, 31
shrd eax, edx, cl
sar edx, cl
cmp ecx, 32
cmovae eax, edx
cmovae edx, ebx
ret
sarq endp
;Calculate 64-bit equal to (a == b)
;bool __cdecl equq(unsigned long long a, unsigned long long b)
;bool __cdecl equq(long long a, long long b)
equq proc, a:qword, b:qword
mov eax, dword ptr [a]
mov edx, dword ptr [a+4]
cmp edx, dword ptr [b+4]
jne l
cmp eax, dword ptr [b]
jne l
mov eax, 1
ret
l:
xor eax, eax
ret
equq endp
;Calcualte 64-bit not equal to (a != b)
;bool __cdecl neqq(unsigned long long a, unsigned long long b)
;bool __cdecl neqq(long long a, long long b)
neqq proc, a:qword, b:qword
mov eax, dword ptr [a]
mov edx, dword ptr [a+4]
cmp edx, dword ptr [b+4]
jne l
cmp eax, dword ptr [b]
jne l
xor eax, eax
ret
l:
mov eax, 1
ret
neqq endp
;Calculate unsigned 64-bit less than (a < b)
;bool __cdecl lesq(unsigned long long a, unsigned long long b)
lesq proc, a:qword, b:qword
mov eax, dword ptr [a]
mov edx, dword ptr [a+4]
cmp eax, dword ptr [b]
sbb edx, dword ptr [b+4]
setb al
and eax, 1
ret
lesq endp
;Calcualte signed 64-bit less than (a < b)
;bool __cdecl ilesq(long long a, long long b)
ilesq proc, a:sqword, b:sqword
mov eax, dword ptr [a]
mov edx, dword ptr [a+4]
cmp eax, dword ptr [b]
sbb edx, dword ptr [b+4]
setl al
and eax, 1
ret
ilesq endp
;Calculate unsigned 64-bit greater than (a > b)
;bool __cdecl gtrq(unsigned long long a, unsigned long long b)
gtrq proc, a:qword, b:qword
mov eax, dword ptr [b]
mov edx, dword ptr [b+4]
cmp eax, dword ptr [a]
sbb edx, dword ptr [a+4]
setb al
and eax, 1
ret
gtrq endp
;Calculate signed 64-bit greater than (a > b)
;bool __cdecl igtrq(long long a, long long b)
igtrq proc, a:sqword, b:sqword
mov eax, dword ptr [b]
mov edx, dword ptr [b+4]
cmp eax, dword ptr [a]
sbb edx, dword ptr [a+4]
setl al
and eax, 1
ret
igtrq endp
;Calculate unsigned 64-bit less than or equal to (a <= b)
;bool __cdecl leqq(unsigned long long a, unsigned long long b)
leqq proc, a:qword, b:qword
mov eax, dword ptr [b]
mov edx, dword ptr [b+4]
cmp eax, dword ptr [a]
sbb edx, dword ptr [a+4]
setnb al
and eax, 1
ret
leqq endp
;Calculate signed 64-bit less than or equal to (a <= b)
;bool __cdecl ileqq(long long a, long long b)
ileqq proc, a:sqword, b:sqword
mov eax, dword ptr [b]
mov edx, dword ptr [b+4]
cmp eax, dword ptr [a]
sbb edx, dword ptr [a+4]
setnl al
and eax, 1
ret
ileqq endp
;Calculate unsigned 64-bit greater than or equal to (a >= b)
;bool __cdecl geqq(unsigned long long a, unsigned long long b)
geqq proc, a:qword, b:qword
mov eax, dword ptr [a]
mov edx, dword ptr [a+4]
cmp eax, dword ptr [b]
sbb edx, dword ptr [b+4]
setnb al
and eax, 1
ret
geqq endp
;Calculate singed 64-bit greater than or equal to (a >= b)
;bool __cdecl igeqq(long long a, long long b)
igeqq proc, a:sqword, b:sqword
mov eax, dword ptr [a]
mov edx, dword ptr [a+4]
cmp eax, dword ptr [b]
sbb edx, dword ptr [b+4]
setnl al
and eax, 1
ret
igeqq endp
end
ifndef QWORDOPS_INC
QWORDOPS_INC = 1
;Calculate signed 64-bit negation (-a)
;long long __cdecl negq(long long a)
negq proto c, a:sqword
;Calculate 64-bit addition (a + b)
;unsigned long long __cdecl addq(unsigned long long a, unsigned long long b)
;long long __cdecl addq(long long a, long long b)
addq proto c, a:qword, b:qword
;Calculate 64-bit substraction (a - b)
;unsigned long long __cdecl subq(unsigned long long a, unsigned long long b)
;long long __cdecl subq(long long a, long long b)
subq proto c, a:qword, b:qword
;Calculate unsigned 64-bit multiplication (a * b)
;unsigned long long __cdecl mulq(unsigned long long a, unsigned long long b)
mulq proto c, a:qword, b:qword
;Calculate signed 64-bit multiplication (a * b)
;long long __cdecl imulq(long long a, long long b)
imulq proto c, a:sqword, b:sqword
;Calculate unsigned 64-bit division (a / b)
;unsigned long long __cdecl divq(unsigned long long a, unsigned long long b)
divq proto c, a:qword, b:qword
;Calculate singed 64-bit division (a / b)
;long long __cdecl idivq(long long a, long long b)
idivq proto c, a:sqword, b:sqword
;Calculate unsigned 64-bit modulo (a % b)
;unsigned long long __cdecl modq(unsigned long long a, unsigned long long b)
modq proto c, a:qword, b:qword
;Calculate signed 64-bit modulo (a % b)
;long long __cdecl imodq(long long a, long long b)
imodq proto c, a:sqword, b:sqword
;Calculate 64-bit bitwise not (~a)
;unsigned long long __cdecl notq(unsigned long long a)
;long long __cdecl notq(long long a)
notq proto c, a:qword
;Calculate 64-bit bitwise and (a & b)
;unsigned long long __cdecl andq(unsigned long long a, unsigned long long b)
;long long __cdecl andq(long long a, long long b)
andq proto c, a:qword, b:qword
;Calculate 64-bit bitwise or (a | b)
;unsigned long long __cdecl orq(unsigned long long a, unsigned long long b)
;long long __cdecl orq(long long a, long long b)
orq proto c, a:qword, b:qword
;Calculate 64-bit bitwise xor (a ^ b)
;unsigned long long __cdecl xorq(unsigned long long a, unsigned long long b)
;long long __cdecl xorq(long long a, long long b)
xorq proto c, a:qword, b:qword
;Calcualte 64-bit left shift (a << b)
;unsigned long long __cdecl shlq(unsigned long long a, unsigned int b)
;long long __cdecl shlq(long long a, unsigned int b)
shlq proto c, a:qword, b:dword
;Calculate unsigned 64-bit logical right shift (a >> b)
;unsigned long long __cdecl shrq(unsigned long long a, unsigned int b)
shrq proto c, a:qword, b:dword
;Calculate signed 64-bit arithmetic right shift (a >> b)
;long long __cdecl sarq(long long a, unsigned int b)
sarq proto c, a:sqword, b:dword
;Calculate 64-bit equal to (a == b)
;bool __cdecl equq(unsigned long long a, unsigned long long b)
;bool __cdecl equq(long long a, long long b)
equq proto c, a:qword, b:qword
;Calcualte 64-bit not equal to (a != b)
;bool __cdecl neqq(unsigned long long a, unsigned long long b)
;bool __cdecl neqq(long long a, long long b)
neqq proto c, a:qword, b:qword
;Calculate unsigned 64-bit less than (a < b)
;bool __cdecl lesq(unsigned long long a, unsigned long long b)
lesq proto c, a:qword, b:qword
;Calcualte signed 64-bit less than (a < b)
;bool __cdecl ilesq(long long a, long long b)
ilesq proto c, a:sqword, b:sqword
;Calculate unsigned 64-bit greater than (a > b)
;bool __cdecl gtrq(unsigned long long a, unsigned long long b)
gtrq proto c, a:qword, b:qword
;Calculate signed 64-bit greater than (a > b)
;bool __cdecl igtrq(long long a, long long b)
igtrq proto c, a:sqword, b:sqword
;Calculate unsigned 64-bit less than or equal to (a <= b)
;bool __cdecl leqq(unsigned long long a, unsigned long long b)
leqq proto c, a:qword, b:qword
;Calculate signed 64-bit less than or equal to (a <= b)
;bool __cdecl ileqq(long long a, long long b)
ileqq proto c, a:sqword, b:sqword
;Calculate unsigned 64-bit greater than or equal to (a >= b)
;bool __cdecl geqq(unsigned long long a, unsigned long long b)
geqq proto c, a:qword, b:qword
;Calculate singed 64-bit greater than or equal to (a >= b)
;bool __cdecl igeqq(long long a, long long b)
igeqq proto c, a:sqword, b:sqword
endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment