【问题标题】:c Inline assembly char array to shortc内联汇编char数组短
【发布时间】:2017-10-30 19:55:51
【问题描述】:

我无法让这段代码工作。在调试时,我看到正确的值/地址在寄存器中,但是当我使用最后一个 mov 时,它仍然不起作用。

我浏览了很多帖子,但没有找到让它发挥作用的方法。所以,基本上,我必须编写一个取自char 数组的日期,并将日期的每个部分放入相应的变量中。不过,我并不完全了解组装的工作原理,我很想得到一些帮助。

这是我的代码:

#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();
}

我可能错了,但是上面的汇编代码部分应该把day的地址/引用放在eax,然后我从date[0]得到2到al,然后把@ 987654330@day.

实际上有一些随机数,它们甚至在最后一条指令之后都不会改变。我的计划是实际使用任何类型的偏移量来连接0 在2 之后,并对其他部分保持相同的方法。但是,由于这不起作用,并且我尝试了许多其他方法(每种方法都会导致相同的错误),所以我在这里要求澄清一下。

【问题讨论】:

标签: c arrays assembly short chars


【解决方案1】:

你有两个问题:

  1. 如何解析字符串。

    如果字符串 si 始终采用 gg/mm/aaaa hh:mm:ss 格式,您可以使用固定索引访问其部分。所以年份可以在索引 [6]、[7]、[8] 和 [9] 中找到。

  2. 如何将字符串转换为整数。

    您可以阅读有关算法的信息。它们并不复杂,只是解释或多或少复杂。在这里,您只有两种数字:两位数字和四位数字。我建议获取值(即整数),就像您向小孩解释的那样:一年的值是 [first digit = "thousands"]*1000 + [second digit = "hundreds"]*100 + [third数字 = “十”]*10 + [第四位 = “单位”]。两位数的值为 [first digit = "tens"]*10 + [second digit = "units"]。

另外,我看到了一个初学者的错误。 AL 是AX 的一部分@ 是EAX 的一部分。如果您更改AL(例如mov al, date[0]),您也会更改EAX。

#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;
}

从 ASCII 字符中分离出可计算的数字。当您从字符串中获取数字时,您会得到 ASCII 字符,例如“20”是 0x32 和 0x30。对于像 2 * 10 + 0 这样的算术,您需要“裸”十进制数。 ASCII 数字位于 0x30 和 0x39 之间的表中。如果你能去掉那个十六进制数中的第一个“3”,你就会得到一个计算机可以计算的数字。这就是AND 0Fh 的目的。前 4 位由 0000 与 - 它们变为 0。最后 4 位由 1111 (F) 与 - 它们保持其原始状态。 0x35 AND 0x0F = 0x05。当您在任何地方看到 48 或 0x30 的减法时 - 这追求相同的目的。

【讨论】:

  • ty ty y 是的,我只是一个初学者,我有点挣扎,因为我之前只用 c# c++ 和 c 编程,这意味着我并没有真正使用堆栈等等...请问“and al, 0fh”是如何隔离十进制数的?
  • @Cicciopalla010:我在答案中添加了解释。我希望它有点可以理解;-)
【解决方案2】:

代码行:

mov al, date[0]

应该将 date[0] - "2" 的值复制到地址中。我相信代码应该是:

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

【讨论】:

  • 如果我尝试这样做,它会给我错误 c2403: register must be base/index in first operand,遗憾的是我有类似的想法并得到相同的错误:(
  • @Cicciopalla010 您是否错过了标记副本的答案,或者有什么不清楚的地方?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-23
  • 2017-11-01
  • 1970-01-01
  • 2018-10-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多