Skip to content

Instantly share code, notes, and snippets.

@antirez
Created January 19, 2012 16:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save antirez/1641112 to your computer and use it in GitHub Desktop.
Save antirez/1641112 to your computer and use it in GitHub Desktop.
Dump of assembler code for function zslGetRank:
zsl argument -> %rdi
o argument -> %rsi
score argument -> %xmm0
x variable -> %rbx
0x0000000000427fd0 <+0>: push %r14
0x0000000000427fd2 <+2>: push %r13
0x0000000000427fd4 <+4>: mov %rsi,%r13
o -> %r13
0x0000000000427fd7 <+7>: push %r12
0x0000000000427fd9 <+9>: push %rbp
0x0000000000427fda <+10>: push %rbx
0x0000000000427fdb <+11>: sub $0x10,%rsp
allocates 16 bytes of stack
0x0000000000427fdf <+15>: mov 0x18(%rdi),%r14d
move zsl->level into %r14d
0x0000000000427fe3 <+19>: mov (%rdi),%rbx
move zsl->header into %rbx (x variable)
0x0000000000427fe6 <+22>: sub $0x1,%r14d
move %r14d is set to (zsl->level-1)
0x0000000000427fea <+26>: js 0x428076 <zslGetRank+166>
return to caller if %r14d (holding the current level) is < 0
0x0000000000427ff0 <+32>: xor %r12d,%r12d
set %r12d to 0 (rank variable)
0x0000000000427ff3 <+35>: nopl 0x0(%rax,%rax,1)
NOP (used for alighment I guess)
0x0000000000427ff8 <+40>: movslq %r14d,%rbp
set %rbp 64 bit register to the value of the 32 bit register %r14d (i variable)
0x0000000000427ffb <+43>: add $0x1,%rbp
0x0000000000427fff <+47>: shl $0x4,%rbp
Compute the (current_level+1)*16 adding+shifting left by 4
0x0000000000428003 <+51>: mov 0x8(%rbx,%rbp,1),%rax
Store x->level[i].forward into %rax
Note that 0x8(%rbx,%rbp,1) is used to access:
%rbx+(%rbp*1)+0x8
Since %rbx points to current node (x variable, type zskiplistNode), and
the 'level' field is at offset 24, and is an array of zskiplistLevel structures
that are 16 bytes each. The 'forward' field is at offset 0 in each of this
structures.
So for instance if level is 2, %rbp is set to (2+1)*16, that is enough to skip
two fields out of three in the zskiplistNode structure, and to select the right
offset of the level array. However we still miss 8 bytes to select the 'forward'
field, and this is why there is the 0x8 displacement.
0x0000000000428008 <+56>: test %rax,%rax
Check if x->level[i] == NULL
0x000000000042800b <+59>: je 0x428052 <zslGetRank+130>
If x->level[i] == NULL go to zslGetRank+130 (while condition false)
0x000000000042800d <+61>: nopl (%rax)
Padding
0x0000000000428010 <+64>: movsd 0x8(%rax),%xmm1
set %xmm1 to x->level[i].forward->score
(note that %rax is x->level[i].forward)
0x0000000000428015 <+69>: ucomisd %xmm1,%xmm0
0x0000000000428019 <+73>: ja 0x42803c <zslGetRank+108>
if x->level[i].forward->score < score go to +108 (while condition true)
0x000000000042801b <+75>: ucomisd %xmm0,%xmm1
0x000000000042801f <+79>: jne 0x428052 <zslGetRank+130>
if x->level[i].forward != score go to +130 (while condition false)
0x0000000000428021 <+81>: jp 0x428052 <zslGetRank+130>
also go to +130 if one of the two is NaN (PF=1)
0x0000000000428023 <+83>: mov (%rax),%rdi
%rdi -> x->level[i].forward->obj
0x0000000000428026 <+86>: mov %r13,%rsi
%r13 -> o
0x0000000000428029 <+89>: movsd %xmm0,(%rsp)
Save %xmm0 before call
0x000000000042802e <+94>: callq 0x41b840 <compareStringObjects>
0x0000000000428033 <+99>: test %eax,%eax
Check if compareStringObjects(x->level[i].forward->obj,o) <= 0
0x0000000000428035 <+101>: movsd (%rsp),%xmm0
Restore %xmm0
0x000000000042803a <+106>: jg 0x428052 <zslGetRank+130>
If instead compareStringObjects() returned > 0, go to +130
0x000000000042803c <+108>: mov 0x10(%rbp,%rbx,1),%eax
%eax -> (%rbp+%rbx+16) -> (x->level[i]->span)
0x0000000000428040 <+112>: mov 0x8(%rbx,%rbp,1),%rbx
%rbx -> x->level[i]->forward (variable x)
0x0000000000428045 <+117>: add %rax,%r12
rank var (%r12) += %rax (that was x->level[i]->span)
0x0000000000428048 <+120>: mov 0x8(%rbx,%rbp,1),%rax
%rax -> x->level[i]->forward
0x000000000042804d <+125>: test %rax,%rax
0x0000000000428050 <+128>: jne 0x428010 <zslGetRank+64>
Loop again if x->level[i]->forward != NULL, jumping to +64
0x0000000000428052 <+130>: mov (%rbx),%rdi
0x0000000000428055 <+133>: test %rdi,%rdi
0x0000000000428058 <+136>: je 0x428070 <zslGetRank+160>
if (x->obj == NULL) jump to +160 (iterate for again)
0x000000000042805a <+138>: mov %r13,%rsi
0x000000000042805d <+141>: movsd %xmm0,(%rsp)
0x0000000000428062 <+146>: callq 0x41b910 <equalStringObjects>
Call equalStringObject with x->obj in %rdi, and o in %rsi
0x0000000000428067 <+151>: test %eax,%eax
0x0000000000428069 <+153>: movsd (%rsp),%xmm0
0x000000000042806e <+158>: jne 0x428079 <zslGetRank+169>
if return value from function is != 0, then the if condition
(x->obj && equalStringObjects(x->obj,o)) is true and we jump to +169
that is where the function returns.
0x0000000000428070 <+160>: sub $0x1,%r14d
0x0000000000428074 <+164>: jns 0x427ff8 <zslGetRank+40>
If variable 'i' (current level, in %r14d) is jet >= 0, iterate the for loop.
0x0000000000428076 <+166>: xor %r12d,%r12d
0x0000000000428079 <+169>: add $0x10,%rsp
0x000000000042807d <+173>: mov %r12,%rax
0x0000000000428080 <+176>: pop %rbx
0x0000000000428081 <+177>: pop %rbp
0x0000000000428082 <+178>: pop %r12
0x0000000000428084 <+180>: pop %r13
0x0000000000428086 <+182>: pop %r14
0x0000000000428088 <+184>: retq
return to the caller, with %r12 (rank) in %eax
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment