Last active
July 10, 2016 14:08
-
-
Save ericherman/9d1a646ad380b27d42b9ff8497e69f32 to your computer and use it in GitHub Desktop.
except in some rare cases, xor swapping is probably silly
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
eric@titan:~/src/code-snips/c$ cat swap-em.c | |
#include <stdio.h> | |
#include <stdint.h> | |
/* this is the way to swap pointers */ | |
void standard_swap(char **left, char **right) | |
{ | |
char *tmp; | |
tmp = *left; | |
*left = *right; | |
*right = tmp; | |
} | |
/* | |
* The xor swapping of pointers is doable, but dumb. | |
* Typically bitwise operations do not work on pointers in C. | |
* Casting to intptr_t is a work-around, but ugly. | |
* Even so, the result does not look a lot more opimized to me. | |
* $ gcc -S -O3 swap-em.c | |
* $ cat swap-em.s | |
*/ | |
void xor_swap(char **left, char **right) | |
{ | |
*left = (char*) (((intptr_t)*left) ^ ((intptr_t)*right)); | |
*right = (char*) (((intptr_t)*left) ^ ((intptr_t)*right)); | |
*left = (char*) (((intptr_t)*left) ^ ((intptr_t)*right)); | |
} | |
int main(int argc, char **argv) | |
{ | |
char *a, *b; | |
char *o, *t; | |
o = "one"; | |
t = "two"; | |
a = o; | |
b = t; | |
printf("initial state: %s, %s\n", a, b); | |
standard_swap(&a, &b); | |
printf("standard swap: %s, %s\n", a, b); | |
xor_swap(&a, &b); | |
printf("xor swap back: %s, %s\n", a, b); | |
return 0; | |
} | |
From x86: | |
eric@titan:~/src/code-snips/c$ gcc -S -O3 swap-em.c | |
eric@titan:~/src/code-snips/c$ cat swap-em.s | |
.file "swap-em.c" | |
.text | |
.p2align 4,,15 | |
.globl standard_swap | |
.type standard_swap, @function | |
standard_swap: | |
.LFB24: | |
.cfi_startproc | |
pushl %ebx | |
.cfi_def_cfa_offset 8 | |
.cfi_offset 3, -8 | |
movl 8(%esp), %edx | |
movl 12(%esp), %eax | |
movl (%edx), %ecx | |
movl (%eax), %ebx | |
movl %ebx, (%edx) | |
movl %ecx, (%eax) | |
popl %ebx | |
.cfi_restore 3 | |
.cfi_def_cfa_offset 4 | |
ret | |
.cfi_endproc | |
.LFE24: | |
.size standard_swap, .-standard_swap | |
.p2align 4,,15 | |
.globl xor_swap | |
.type xor_swap, @function | |
xor_swap: | |
.LFB25: | |
.cfi_startproc | |
movl 4(%esp), %eax | |
movl 8(%esp), %ecx | |
movl (%eax), %edx | |
xorl (%ecx), %edx | |
movl %edx, (%eax) | |
xorl (%ecx), %edx | |
movl %edx, (%ecx) | |
xorl %edx, (%eax) | |
ret | |
.cfi_endproc | |
.LFE25: | |
.size xor_swap, .-xor_swap | |
.section .rodata.str1.1,"aMS",@progbits,1 | |
.LC0: | |
.string "two" | |
.LC1: | |
.string "one" | |
.LC2: | |
.string "initial state: %s, %s\n" | |
.LC3: | |
.string "standard swap: %s, %s\n" | |
.LC4: | |
.string "xor swap back: %s, %s\n" | |
.section .text.startup,"ax",@progbits | |
.p2align 4,,15 | |
.globl main | |
.type main, @function | |
main: | |
.LFB26: | |
.cfi_startproc | |
pushl %ebp | |
.cfi_def_cfa_offset 8 | |
.cfi_offset 5, -8 | |
movl %esp, %ebp | |
.cfi_def_cfa_register 5 | |
andl $-16, %esp | |
subl $16, %esp | |
movl $.LC0, 12(%esp) | |
movl $.LC1, 8(%esp) | |
movl $.LC2, 4(%esp) | |
movl $1, (%esp) | |
call __printf_chk | |
movl $.LC1, 12(%esp) | |
movl $.LC0, 8(%esp) | |
movl $.LC3, 4(%esp) | |
movl $1, (%esp) | |
call __printf_chk | |
movl $.LC0, 12(%esp) | |
movl $.LC1, 8(%esp) | |
movl $.LC4, 4(%esp) | |
movl $1, (%esp) | |
call __printf_chk | |
xorl %eax, %eax | |
leave | |
.cfi_restore 5 | |
.cfi_def_cfa 4, 4 | |
ret | |
.cfi_endproc | |
.LFE26: | |
.size main, .-main | |
.ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4" | |
.section .note.GNU-stack,"",@progbits | |
eric@titan:~/src/code-snips/c$ | |
From ARM: | |
eric@localhost:~/src/code-snips/c$ gcc -S -O3 swap-em.c | |
eric@localhost:~/src/code-snips/c$ cat swap-em.s | |
.arch armv7-a | |
.eabi_attribute 28, 1 | |
.fpu vfpv3-d16 | |
.eabi_attribute 20, 1 | |
.eabi_attribute 21, 1 | |
.eabi_attribute 23, 3 | |
.eabi_attribute 24, 1 | |
.eabi_attribute 25, 1 | |
.eabi_attribute 26, 2 | |
.eabi_attribute 30, 2 | |
.eabi_attribute 34, 1 | |
.eabi_attribute 18, 4 | |
.file "swap-em.c" | |
.text | |
.align 2 | |
.global standard_swap | |
.syntax unified | |
.thumb | |
.thumb_func | |
.type standard_swap, %function | |
standard_swap: | |
@ args = 0, pretend = 0, frame = 0 | |
@ frame_needed = 0, uses_anonymous_args = 0 | |
@ link register save eliminated. | |
ldr r3, [r0] | |
ldr r2, [r1] | |
str r2, [r0] | |
str r3, [r1] | |
bx lr | |
.size standard_swap, .-standard_swap | |
.align 2 | |
.global xor_swap | |
.syntax unified | |
.thumb | |
.thumb_func | |
.type xor_swap, %function | |
xor_swap: | |
@ args = 0, pretend = 0, frame = 0 | |
@ frame_needed = 0, uses_anonymous_args = 0 | |
@ link register save eliminated. | |
ldr r2, [r0] | |
ldr r3, [r1] | |
eors r3, r3, r2 | |
str r3, [r0] | |
ldr r2, [r1] | |
eors r3, r3, r2 | |
str r3, [r1] | |
ldr r2, [r0] | |
eors r3, r3, r2 | |
str r3, [r0] | |
bx lr | |
.size xor_swap, .-xor_swap | |
.section .text.startup,"ax",%progbits | |
.align 2 | |
.global main | |
.syntax unified | |
.thumb | |
.thumb_func | |
.type main, %function | |
main: | |
@ args = 0, pretend = 0, frame = 0 | |
@ frame_needed = 0, uses_anonymous_args = 0 | |
push {r3, r4, r5, lr} | |
movw r5, #:lower16:.LC0 | |
movw r4, #:lower16:.LC1 | |
movt r5, #:upper16:.LC0 | |
movt r4, #:upper16:.LC1 | |
movw r1, #:lower16:.LC2 | |
mov r3, r5 | |
movt r1, #:upper16:.LC2 | |
mov r2, r4 | |
movs r0, #1 | |
bl __printf_chk | |
mov r3, r4 | |
mov r2, r5 | |
movw r1, #:lower16:.LC3 | |
movs r0, #1 | |
movt r1, #:upper16:.LC3 | |
bl __printf_chk | |
mov r3, r5 | |
mov r2, r4 | |
movw r1, #:lower16:.LC4 | |
movs r0, #1 | |
movt r1, #:upper16:.LC4 | |
bl __printf_chk | |
movs r0, #0 | |
pop {r3, r4, r5, pc} | |
.size main, .-main | |
.section .rodata.str1.4,"aMS",%progbits,1 | |
.align 2 | |
.LC0: | |
.ascii "two\000" | |
.LC1: | |
.ascii "one\000" | |
.LC2: | |
.ascii "initial state: %s, %s\012\000" | |
.space 1 | |
.LC3: | |
.ascii "standard swap: %s, %s\012\000" | |
.space 1 | |
.LC4: | |
.ascii "xor swap back: %s, %s\012\000" | |
.ident "GCC: (Ubuntu/Linaro 5.4.0-3ubuntu1~12.04) 5.4.0 20160603" | |
.section .note.GNU-stack,"",%progbits | |
eric@localhost:~/src/code-snips/c$ cat /proc/cpuinfo |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment