-2

I can't manage to make this code work. While debugging, I see the right values/addresses are in the registers but, still, when I use the last mov it doesn't work.

I've browsed a ton of posts but didn't manage to find a way to make it work. So, basically, I have to compose a date taken from a char array and put every part of the date in the corresponding variable. Still, I don't fully understand how assembly works and I'd love to receive some help.

Here is my code:

#include <stdio.h>
void main()
{
    // Input
    char date[] = "20/06/1999 13:23:47";    //gg/mm/aaaa hh:mm:ss

                                            // Output
    unsigned short day;
    unsigned short month;
    unsigned short year;
    unsigned short hour;
    unsigned short minute;
    unsigned short second;

    __asm
    {
        lea eax,day
        mov al, date[0]
        mov [eax],al
    }

    // Stampa su video
    printf("day: %i month: %i year: %i hour: %i minute: %i second: %i \n", day,month,year,hour, minute, second);
    printf("press a key to go");
    getchar();
}

I may be wrong, but the part of assembly code up there should put in eax the address/reference for day, then I get 2 from date[0] into al and then put the 2 in day.

Actually there are some random numbers and they don't even change after the last instruction. My plan was to actually use an offset of any kind to concatenate the 0 after the 2, and keep the same method for other parts. But, since that doesn't work, and I tried many other approaches (each one resulting in the same error) I'm here asking for some clarity.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • 5
    Possible duplicate of [Assembly programming memory Allocating EAX vs Ax, AH, AL](https://stackoverflow.com/questions/15191178/assembly-programming-memory-allocating-eax-vs-ax-ah-al) (plus **use debugger** to see, what happens with address in `eax` when you do `mov al, date[0]`) – Ped7g May 30 '17 at 11:11

2 Answers2

1

You've got two problems:

  1. How to parse a string.

    If the string si always in the format gg/mm/aaaa hh:mm:ss you can access to its parts with fixed indices. So the year can be found at the indices [6], [7], [8], and [9].

  2. How to convert a string into an integer.

    You can read about the algorithms. They are not complicated, just explained more or less complicated. Here, you've got just two kinds of numbers: those with two digits and those with four digits. I suggest to get the value (i.e. integer) as you would explain it to a little child: The value of a year is [first digit = "thousands"]*1000 + [second digit = "hundreds"]*100 + [third digit = "tens"]*10 + [fourth digit = "units"]. The value of a two-digit-number is [first digit = "tens"]*10 + [second digit = "units"].

Additionally, I see a beginner's mistake. AL is a part of AX is a part of EAX. If you change AL (e.g. mov al, date[0]), you change EAX as well.

#include <stdio.h>

int main ( void )
{
    // Input
    char date[] = "20/06/1999 13:23:47";    //gg/mm/aaaa hh:mm:ss

                                        // Output
    unsigned short day;
    unsigned short month;
    unsigned short year;
    unsigned short hour;
    unsigned short minute;
    unsigned short second;

    __asm
    {
        mov cl, 10                  ; Multiplicator

        mov al, date[0]             ; First digit
        and al, 0Fh                 ; Isolate the decimal number of the ASCII character
        mul cl                      ; AX = AL * CL => tens
        mov dl, date[1]             ; Second digit
        and dx, 0Fh                 ; Isolate the decimal number of the ASCII character
        add ax, dx                  ; Add the tens and the units
        mov [day],ax                ; Save the result

        mov al, date[3]             ; First digit
        and al, 0Fh                 ; Isolate the decimal number of the ASCII character
        mul cl                      ; AX = AL * CL
        mov dl, date[4]             ; Second digit
        and dx, 0Fh                 ; Isolate the decimal number of the ASCII character
        add ax, dx                  ; Add the tens and the units
        mov [month],ax              ; Save the result

        movzx ax, byte ptr date[6]  ; Load one byte into a word register
        and al, 0Fh                 ; Isolate the decimal number of the ASCII character
        imul dx, ax, 1000           ; DX = AX * 1000 => millenium
        movzx ax, byte ptr date[7]  ; Load one byte into a word register
        and al, 0Fh                 ; Isolate the decimal number of the ASCII character
        imul ax, ax, 100            ; AX = AX * 100
        add dx, ax                  ; Add it to the millenium => 1900
        movzx ax, byte ptr date[8]  ; Load one byte into a word register
        and al, 0Fh                 ; Isolate the decimal number of the ASCII character
        imul ax, ax, 10
        add dx, ax                  ; Add it => 1990
        movzx ax, byte ptr date[9]  ; Load one byte into a word register
        and al, 0Fh                 ; Isolate the decimal number of the ASCII character
        add dx, ax                  ; Add it => 1999
        mov [year], dx              ; Save the result (DX!)

        mov al, date[11]            ; First digit
        and al, 0Fh                 ; Isolate the decimal number of the ASCII character
        mul cl                      ; AX = AL * CL
        mov dl, date[12]            ; Second digit
        and dx, 0Fh                 ; Isolate the decimal number of the ASCII character
        add ax, dx                  ; Add the tens and the units
        mov [hour], ax              ; Save the result

        mov al, date[14]            ; First digit
        and al, 0Fh                 ; Isolate the decimal number of the ASCII character
        mul cl                      ; AX = AL * CL
        mov dl, date[15]            ; Second digit
        and dx, 0Fh                 ; Isolate the decimal number of the ASCII character
        add ax, dx                  ; Add the tens and the units
        mov [minute],ax             ; Save the result

        mov al, date[17]            ; First digit
        and al, 0Fh                 ; Isolate the decimal number of the ASCII character
        mul cl                      ; AX = AL * CL
        mov dl, date[18]            ; Second digit
        and dx, 0Fh                 ; Isolate the decimal number of the ASCII character
        add ax, dx                  ; Add the tens and the units
        mov [second],ax             ; Save the result
    }

    // Stampa su video
    printf("day: %i month: %i year: %i hour: %i minute: %i second: %i \n", day,month,year,hour, minute, second);

    // printf("press a key to go");
    // getchar();

    return 0;
}

Isolating a calculable number from an ASCII character. When you fetch a number from a string you get ASCII characters, e.g "20" is 0x32 and 0x30. For arithmetics like 2 * 10 + 0 you need the "bare" decimal number. The ASCII digits resides in the table between 0x30 and 0x39. If you can get rid of the first "3" in that hexadecimal number you get a number that the computer can calculate. This is the purpose of the AND 0Fh. The first 4 bits are ANDed by 0000 - they become 0. The last 4 bits are ANDed by 1111 (F) - they keep their original state. 0x35 AND 0x0F = 0x05. When you see anywhere a subtraction by 48 or 0x30 - this pursues the same purpose.

Community
  • 1
  • 1
rkhb
  • 14,159
  • 7
  • 32
  • 60
  • ty ty ty yeah im just a beginner and im kinda struggling since i ve only programmed with c# c++ and c before wich means i don't have really worked a lot with stack and so on... id ask how the "and al, 0fh"works to isolate the decimal number? – Cicciopalla010 May 31 '17 at 09:53
  • @Cicciopalla010: I added an explanation to the answer. I hope it is a little understandable ;-) – rkhb May 31 '17 at 14:31
-1

The line of code:

mov al, date[0]

should be copying value of date[0] - "2" into address. I believe the code should be as:

__asm
{
    lea eax,day
    mov [al], date[0]
    mov [eax],al
}
praty
  • 535
  • 2
  • 9
  • if i try this it gives me error c2403: register must be base/index in first operand, sadly i had a similar idea and got the same error :( – Cicciopalla010 May 30 '17 at 11:43
  • @Cicciopalla010 did you miss the answer from the marked duplicate, or something was not clear? – Ped7g May 30 '17 at 17:56