Skip to content

Instantly share code, notes, and snippets.

@tiqwab
Last active September 6, 2019 10:17
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 tiqwab/7172aa60530d1cd5cab8452e359ec7be to your computer and use it in GitHub Desktop.
Save tiqwab/7172aa60530d1cd5cab8452e359ec7be to your computer and use it in GitHub Desktop.
Signed division by 2^n

(from Problem4 in https://web.stanford.edu/class/archive/cs/cs107/cs107.1186/exams/f1.pdf)

The below C code:

#include <stdlib.h>

int pinky(char *param1, int *param2) {
    char *str = NULL;
    int local = strtol(param1, &str, 0x10);
    if (local - 7 > 12) {
        local += param2[3];
    }
    return local / 4;
}

int main(int argc, char *argv[]) {
    char *param1 = "foo";
    int param2 = 17;
    pinky("foo", &param2);

    return 0;
}

generates the below assembly (by gcc -o pinky.s -S -Og pinky.c).

	.file	"pinky.c"
	.text
	.globl	pinky
	.type	pinky, @function
pinky:
.LFB11:
	.cfi_startproc
	pushq	%rbx
	.cfi_def_cfa_offset 16
	.cfi_offset 3, -16
	subq	$16, %rsp
	.cfi_def_cfa_offset 32
	movq	%rsi, %rbx
	movq	%fs:40, %rax
	movq	%rax, 8(%rsp)
	xorl	%eax, %eax
	movq	$0, (%rsp)
	movq	%rsp, %rsi
	movl	$16, %edx
	call	strtol@PLT
	movl	%eax, %edx
	cmpl	$19, %eax
	jle	.L2
	addl	12(%rbx), %edx
.L2:
	leal	3(%rdx), %eax
	testl	%edx, %edx
	cmovns	%edx, %eax
	sarl	$2, %eax
	movq	8(%rsp), %rcx
	xorq	%fs:40, %rcx
	jne	.L5
	addq	$16, %rsp
	.cfi_remember_state
	.cfi_def_cfa_offset 16
	popq	%rbx
	.cfi_def_cfa_offset 8
	ret
.L5:
	.cfi_restore_state
	call	__stack_chk_fail@PLT
	.cfi_endproc
.LFE11:
	.size	pinky, .-pinky
	.section	.rodata.str1.1,"aMS",@progbits,1
.LC0:
	.string	"foo"
	.text
	.globl	main
	.type	main, @function
main:
.LFB12:
	.cfi_startproc
	pushq	%rbx
	.cfi_def_cfa_offset 16
	.cfi_offset 3, -16
	subq	$16, %rsp
	.cfi_def_cfa_offset 32
	movl	$40, %ebx
	movq	%fs:(%rbx), %rax
	movq	%rax, 8(%rsp)
	xorl	%eax, %eax
	movl	$17, 4(%rsp)
	leaq	4(%rsp), %rsi
	leaq	.LC0(%rip), %rdi
	call	pinky
	movq	8(%rsp), %rax
	xorq	%fs:(%rbx), %rax
	jne	.L9
	movl	$0, %eax
	addq	$16, %rsp
	.cfi_remember_state
	.cfi_def_cfa_offset 16
	popq	%rbx
	.cfi_def_cfa_offset 8
	ret
.L9:
	.cfi_restore_state
	call	__stack_chk_fail@PLT
	.cfi_endproc
.LFE12:
	.size	main, .-main
	.ident	"GCC: (GNU) 9.1.0"
	.section	.note.GNU-stack,"",@progbits

This shows that local / 4 is performed by the four operations:

	leal	3(%rdx), %eax ; this is not for calculating address, but for add and store to a register in a single operation
	testl	%edx, %edx ; compute logical AND of operands and set SF, ZF, and PF flags
	cmovns	%edx, %eax ; move if not signed (SF=0)
	sarl	$2, %eax

The detail is explained here.

@tiqwab
Copy link
Author

tiqwab commented Sep 6, 2019

The format of assembly gcc generates is AT&T (https://en.wikibooks.org/wiki/X86_Assembly/GAS_Syntax) in default.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment