kohlrak icon

Untitled

kohlrak | PRO | 07/17/17 08:39:41 PM UTC | 0 ⭐ | 263 👁️ | Never ⏰ | []
ASM (NASM) |

0 B

|

None

|

0 👍

/

0 👎

[kohlrak@kohlrak-server temp]$ cat main.cpp
#include <stdio.h>
#include <stdlib.h>
 
template <typename T>
T swap_endian(T u)
{
    //static_assert (CHAR_BIT == 8, "CHAR_BIT != 8"); //Totally unnecessary.
 
    union
    {
        T u;
        unsigned char u8[sizeof(T)];
    } source, dest;
 
    source.u = u;
 
    for (T k = 0; k < sizeof(T); k++)
        dest.u8[k] = source.u8[sizeof(T) - k - 1];
 
    return dest.u;
}
 
int main(int argc, char **argv){
        int le = atoi(argv[1]), be; //For the sake of example, we'll just assume the user will send us the correct number of params.
        be=swap_endian<int>(le);
        printf("LE: 0x%08x\nBE: 0x%08x\n", le, be);
        return 0;
}
[kohlrak@kohlrak-server temp]$ ./a.out 328328
LE: 0x00050288
BE: 0x88020500
[kohlrak@kohlrak-server temp]$ g++ main.cpp -S -masm=intel -O9
[kohlrak@kohlrak-server temp]$ cat main.s
        .file   "main.cpp"
        .intel_syntax noprefix
        .section        .rodata.str1.1,"aMS",@progbits,1
.LC0:
        .string "LE: 0x%08x\nBE: 0x%08x\n"
        .section        .text.startup,"ax",@progbits
        .globl  main
main:
.LFB27:                 #begin variable preserving
        lea     ecx, [esp+4] 
        and     esp, -16        #create 2 int variables (taking advantage of it being aligned to use the faster and instruction)
        push    DWORD PTR [ecx-4]
        push    ebp
        mov     ebp, esp        #end variable preserving
        push    ebx         #begin atoi(argv[1]). note: the function atoi is actually here, rather than calling atoi.
        push    ecx
        mov     eax, DWORD PTR [ecx+4]
        sub     esp, 4
        push    10
        push    0
        push    DWORD PTR [eax+4]
        call    strtol          #end atoi(argv[1]), note return value is in eax register AKA beginning of swap_endian(le)
        mov     ecx, eax        #put result of atoi(argv[1]) into ecx register.
        xor     edx, edx        #empty edx register (RAM efficient)
        mov     ebx, eax        #put result of atoi(argv[1]) into ebx register.
        shr     ecx, 24         #performing C++'s >>24 on ecx
        sal     ebx, 24         #performing C++ <<24 on ebx.
        add     esp, 12         #deleting the variables used by atoi(argv[1]).
        mov     dl, cl          #moving the first byte of ecx to edx (aka edx=ecx&0xFF)
        mov     ecx, eax        #moving that return from atoi(argv[1]) into ecx
        shr     ecx, 16         #ecx>>16
        mov     dh, cl          #moving the result from that into the second byte of edx
        movzx   ecx, ah         #moving the second byte of the return of atoi(argv[1]) to ecx
        sal     ecx, 16         #ecx<<16
        movzx   edx, dx         #edx=edx&0xFFFF;
        or      edx, ecx        #edx|=ecx
        or      edx, ebx        #edx|=ebx AKA end of swap_endian(le), result in edx
        push    edx         #begin printf("LE: 0x%08x\nBE: 0x%08x\n", le, be);
        push    eax
        push    OFFSET FLAT:.LC0
        call    printf
        add     esp, 16
        lea     esp, [ebp-8]
        xor     eax, eax        #set eax to 0
        pop     ecx         #end printf("LE: 0x%08x\nBE: 0x%08x\n", le, be);
        pop     ebx
        pop     ebp
        lea     esp, [ecx-4]        #restore preserved registers and variables
        ret             #return; NOTE: eax is the register that holds return values, which is 0.

Comments