zoukankan      html  css  js  c++  java
  • 把x指针指向的4个字节次序颠倒过来

    举例:x指向的内存地址,其字节内容从低到高依次分别为c1,c2,c3,c4(Delphi读取一个integer的时候,结果是c4c3c2c1,其排列规则是"高高低低"),那么结果是c4,c3,c2,c1(Delphi读取一个integer的时候,结果是c1c2c3c4)

    用delphi写的程序,把x指针指向的4个字节次序颠倒过来:

    function toulong(x: pchar): longword;
    begin
    result := (longword(x^) shl 24) or
    (longword((x + 1)^) shl 16) or
    (longword((x + 2)^) shl 8) or
    (longword((x + 3)^));
    end;

    以下是用delphi的嵌入式汇编写法:

    function toulong(x: pchar): longword;
    asm
    mov esi,eax // 读取x指针的值(也就是某一个内存地址)到esi(esi是通用寄存器,一般可以随便使用)。即esi=x
    mov ax,[esi] // 从这个内存地址里读取两个字节的内容到ax里。即ax=c2c1(注意,intel倒着吃)
    xchg ah,al // 把ax里两个字节位置交换一下。即ax=c1c2
    shl eax,16 // 交换完以后左移到eax的高2位字节。即eax=c1c200
    mov ax,[esi+2] // 把esi往后移动2个字节读取内存数据到ax里,即ax=c4c3(注意,intel倒着吃)
    xchg ah,al // 把ax里两个字节位置交换一下。即ax=c3c4。加上之前计算好的eax高2位字节,结果即此时eax=c1c2c3c4,如果写回内存的话,内存里的值从低到高依次为c4c3c2c1,但Delphi倒着吃,又会读出一个integer的数据为c1c2c3c4)
    end;

    说明:默认情况下,delphi使用“register”方式,若参数在3个已内,将分别使用eax、edx和ecx,超过3个参数部分将使用堆栈。返回参数的存放视长度而定,例如8位用al返回,16位用ax,32位用eax,64位用用两个32位寄存器edx:eax,其中eax是低位。

    效率:本例asm大约比delphi或c快50%。

    ======================================================

    做了个Delphi程序验证:

    procedure TForm1.Button3Click(Sender: TObject);
    var
    i: integer;
    p: PInteger;
    x: PChar;
    begin
    i:=$04030201; // 注意,只有这样,才会内存的值从低到高依次是01020304
    p:=@i;
    ShowMessage(IntToStr(Integer(p^)));
    x:=pchar(p);
    ShowMessage(IntToStr(toulong(x)));
    end;

    Hex 01020304 = Dec 16909060
    Hex 04030201 = Dec 67305985

    注意,观察这个的汇编代码,很有意思。

    ======================================================

    再用VC写一遍,汇编代码主体都不必,就是改变了关于参数传递约定那部分

    #include "stdafx.h"
    
    int toulong(char* p)
    {
        int fff;
        __asm {
            mov eax, p // EAX不再是第一个参数的值了,所以要自己写
            mov esi,eax 
            mov ax,[esi] 
            xchg ah,al 
            shl eax,16 
            mov ax,[esi+2] 
            xchg ah,al 
            mov fff, eax // EAX不再是自动的返回值了,所以要自己写
        }
        return fff;
    }
    
    int main(int argc, char* argv[])
    {
        int i=0x04030201;
        printf("after: %d !
    ", i);
        int* p=&i;
        int j=toulong((char*)p);
        printf("after: %d !
    ", j);
        return 0;
    }

    ===========================================

    不清楚对象在内存里的排列是怎么个倒序。以后再研究。

  • 相关阅读:
    stm32 oled学习
    PWM输出配置步骤
    IIC通信笔记
    运算放大器原理
    stm32跑马灯实现及蜂鸣器实验
    一个字节多少位
    pyQT编写界面调用摄像头
    PAT Advanced 1151 LCA in a Binary Tree (30) [树的遍历,LCA算法]
    PAT Advanced 1143 Lowest Common Ancestor (30) [二叉查找树 LCA]
    PAT Advanced 1147 Heaps (30) [堆,树的遍历]
  • 原文地址:https://www.cnblogs.com/findumars/p/3717999.html
Copyright © 2011-2022 走看看