【问题标题】:vb Integer to c++ to ML32 to c++ to vb UIntegervb 整数到 c++ 到 ML32 到 c++ 到 vb UInteger
【发布时间】:2015-12-17 19:11:27
【问题描述】:

我正在尝试通过 ML32 中的直接逐位传输将 vb 2015 Integer 更改为 vb 2015 UInteger。从 vb2015 开始,我在 dll 中调用了一个 vc++ 2015 函数,该函数使用内联汇编程序来实现更改。

通过这样做,我可以取一个负整数,例如 -633593090 = &HDA3C22FE = 11011010001111000010001011111110b

并将其更改为 UInteger = 11011010001111000010001011111110b = &HDA3C22FE = 3661374206

与看似简单的“uTest1 = CUInt(iTest1)”相反,它会为 iTest1 抛出 System.OverflowException 异常。

我的代码可以正常工作,但我对小改进的可能性很感兴趣。

在 vb 2015 中,我声明对 vc++ 2015 dll 的访问权限如下:

' vb Integer --> c++ signed long --> c++ unsigned long --> vb UInteger -- Works!
'   by direct copy of bits through x86 ML32
'   4 bytes = 32 bits
<DllImport("StringTest.dll", EntryPoint:="bitConvert", SetLastError:=True, CharSet:=CharSet.Ansi, ExactSpelling:=True, CallingConvention:=CallingConvention.Cdecl)>
Private Shared Function bitConvertTester(ByRef varSInt As Integer, ByRef varUInt As UInteger) As Integer
    ' Must be "Shared"
    ' Must be "ByRef"
    ' Do not try varSInt As "Signed Integer" or varUInt As "Unsigned Integer" --> Syntax Error
    ' Leave the body of the function empty
End Function

我使用这个 vb 2015 代码来实际调用 dll 中的 vc++ 2015 函数:

    ' Third Method - Partial - Works!
    Dim pCTest As Color
    Dim iTest As Integer
    Dim uTest As UInteger
    Dim returnCode As Integer
    pCTest = Color.FromArgb(&HDA, &H3C, &H22, &HFE)
    iTest = pCTest.ToArgb
    System.Diagnostics.Debug.Write(iTest.ToString + vbCrLf)
    System.Diagnostics.Debug.Write(Hex(iTest) + vbCrLf)

    ' vb Integer --> c++ signed long --> c++ unsigned long --> vb UInteger
    '   by direct copy of bits through x86 ML32
    '   4 bytes = 32 bits
    ' Note: Function prototype is "ByRef", but this MUST 
    '   NOT go in this test call (causes a syntax error).
    returnCode = bitConvertTester(iTest, uTest)

    System.Diagnostics.Debug.Write(uTest.ToString + vbCrLf)
    System.Diagnostics.Debug.Write(Hex(uTest) + vbCrLf)

这里是 vc++ 2015 dll 函数本身:

    #define EXPORT_VB extern "C" __declspec(dllexport)
    // vb Integer --> c++ signed long --> c++ unsigned long --> vb UInteger -- Works!
    //   by direct copy of bits through x86 ML32
    //   4 bytes = 32 bits
    EXPORT_VB long __cdecl bitConvert(signed long *varSInt, unsigned long *varUInt)
    {
        // Intermediate variables are required for ML32 access.
        signed long varSInt1;
        unsigned long varUInt1;
        varSInt1 = *varSInt;
        __asm
        {
            mov EAX, varSInt1
            mov varUInt1, EAX
        }
        *varUInt = varUInt1;
        return 1;                   // Success Code
    }

我使用变量 ByRef 从 vb 2015 调用 vc++ 2015 dll 函数,以便 dll 函数可以根据需要通过 *varSInt 和 *varUInt 使用指针来更改 vb 2015 变量。

我的问题是:在 vc++ __asm 块中,ML32 代码有什么方法可以直接访问 *varSInt 和 *varUInt,而无需通过 varSInt1 和 varUInt1 中间变量?

顺便说一句,vb 2015 代码使用:

 Imports System
 Imports System.IO
 Imports System.Text
 Imports System.Runtime.InteropServices

而vc++ 2015代码使用:

 #include "stdafx.h"
 #include <stdexcept>
 #include <string.h> 

(我对 Microsoft 文档感到沮丧的一件事是未能包含使用文档描述的功能所需的“Imports”或“#include”语句列表)。

【问题讨论】:

  • 无论如何都不需要汇编,因为 C 可以很好地从有符号转换为无符号。当然,您也可以在 vb.net 中完成所有操作。我希望您只是将其作为练习。
  • 是的,我是一名退休工程师,这是我退休后为了好玩而做的事情。但是,至少在 vb 中(我没有在 vc 中尝试过,但我怀疑它可能是相同的),如果有符号为负,则从有符号到无符号的转换会抛出 System.OverflowException。

标签: c++ vb.net assembly dll


【解决方案1】:

我知道您说您只是将其作为练习,但是有一种相对简单的方法可以在 VB(或 C# 中)中获得您想要的结果。

Function ToUInt(value As Integer) As UInteger
    Return CUInt(If(value < 0, UInteger.MaxValue + value + 1, value))
End Function

【讨论】:

  • 谢谢你,布莱克伍德。这确实很优雅,而且非常紧凑。但我的主要目标是提高和增加我对如何编写 c++ 和 ML32 dll 代码以供 vb 使用的理解。例如,在这种情况下,我最终可能希望在将有符号整数加载到 EAX 和然后将(修改的)无符号整数返回到 vb 之间执行其他 ML32 操作。而且,鉴于此,我想知道是否有办法避免使用中间变量。
猜你喜欢
  • 2010-12-15
  • 2016-08-24
  • 2011-12-10
  • 2016-04-22
  • 2016-11-11
  • 1970-01-01
  • 1970-01-01
  • 2014-12-24
  • 2018-05-09
相关资源
最近更新 更多