Assembly Language for Beginners

(Jeff_L) #1

1.20. ARRAYS


In fact yes, if you represent the list of strings as a two-dimensional array:


#include <stdio.h>
#include <assert.h>


const char month2[12][10]=
{
{ 'J','a','n','u','a','r','y', 0, 0, 0 },
{ 'F','e','b','r','u','a','r','y', 0, 0 },
{ 'M','a','r','c','h', 0, 0, 0, 0, 0 },
{ 'A','p','r','i','l', 0, 0, 0, 0, 0 },
{ 'M','a','y', 0, 0, 0, 0, 0, 0, 0 },
{ 'J','u','n','e', 0, 0, 0, 0, 0, 0 },
{ 'J','u','l','y', 0, 0, 0, 0, 0, 0 },
{ 'A','u','g','u','s','t', 0, 0, 0, 0 },
{ 'S','e','p','t','e','m','b','e','r', 0 },
{ 'O','c','t','o','b','e','r', 0, 0, 0 },
{ 'N','o','v','e','m','b','e','r', 0, 0 },
{ 'D','e','c','e','m','b','e','r', 0, 0 }
};


// in 0..11 range
const char* get_month2 (int month)
{
return &month2[month][0];
};


Here is what we’ve get:


Listing 1.254: Optimizing MSVC 2013 x64

month2 DB 04aH
DB 061H
DB 06eH
DB 075H
DB 061H
DB 072H
DB 079H
DB 00H
DB 00H
DB 00H
...


get_month2 PROC
; sign-extend input argument and promote to 64-bit value
movsxd rax, ecx
lea rcx, QWORD PTR [rax+rax4]
; RCX=month+month
4=month5
lea rax, OFFSET FLAT:month2
; RAX=pointer to table
lea rax, QWORD PTR [rax+rcx
2]
; RAX=pointer to table + RCX2=pointer to table + month52=pointer to table + month10
ret 0
get_month2 ENDP


There are no memory accesses at all.


All this function does is to calculate a point at which the first character of the name of the month is:
pointer_to_the_table+month∗ 10.


There are also twoLEAinstructions, which effectively work as severalMULandMOVinstructions.


The width of the array is 10 bytes.


Indeed, the longest string here—“September”—is 9 bytes, and plus the terminating zero is 10 bytes.


The rest of the month names are padded by zero bytes, so they all occupy the same space (10 bytes).


Thus, our function works even faster, because all string start at an address which can be calculated easily.


Optimizing GCC 4.9 can do it even shorter:

Free download pdf