主题:如何在VB中处理64位整形数据?
襄河渔夫
[专家分:0] 发布于 2009-05-13 23:13:00
VB中的整型数据是16位或者32位的,现在文件中有一个64位的整形数据,要用读出它,用什么处理方法呢?
回复列表 (共22个回复)
11 楼
oO羽姿Oo [专家分:600] 发布于 2009-05-20 10:01:00
[em2]
12 楼
oO羽姿Oo [专家分:600] 发布于 2009-05-20 10:34:00
[em2]
13 楼
广告专业户 [专家分:400] 发布于 2009-05-21 01:31:00
很不幸,俺真没亲自试过。不过俺也算科班出身,学过编译原理、操作系统、汇编语言、组成原理、C/C++、VB、Delphi,关于数据长度这点,俺心里还是很清晰的。(指令+操作数编码为不等长二进制,执行时读到内存由CPU译码执行,也就是我前面说的“固化”)
然后又很不幸,俺现在用的是Vista x64 With SP1,也就是你传说中的“64位系统”,所以在你的提示下,俺现在可以写代码亲自试一下。
[code=c]
Option Explicit
Private Const TEMP_FILE As String = "D:\temp.bin"
Private Sub WriteFile()
Dim byt(15) As Byte
Dim i As Long
For i = 1 To 16
byt(i - 1) = &H10 + i
Next
Open TEMP_FILE For Binary Access Write As #1
Put #1, , byt
Close #1
End Sub
[/code]
对于这段,你没有异议吧?我写入的是Byte,不论在哪都一样,最张文件十六进制形式是这样的:
11 12 13 14 15 16 17 18 ...,一共16字节,足够了吧?
[code=c]
Private Sub Read1Long()
Dim ret As Long
Open TEMP_FILE For Binary Access Read As #1
Get #1, , ret
Close #1
MsgBox (Hex(ret))
End Sub
[/code]
很明显,这段是读取一个Long值并用对话框显示的。
OK,让我们调用一下:
[code=c]
Private Sub Form_Load()
WriteFile
Read1Long
Kill TEMP_FILE
End
End Sub
[/code]
写入文件,读取,删除
编译后,在我x64上结果为“14131211”,也就是一个4字节的整数,因为x86兼容的CPU是低位在前的,结果也符合我们事先的预期。
然后,我把这个程序压缩发给使用32位XP的朋友,叫他运行一下发回结果给我。很不幸,结果一样还是“14131211”
如果结果与我事先预期的不一致,那我这么多年真是白学了。
另外要说一下的就是我对VB6的一些理解:VB6已经算是编译型的语言了(除非你特意到编译选项里选择P-Code),它编译的最终结果为Native Code(本地/原生代码),只是很多函数要跳到msvbvm60.dll里面去执行而已。
对于.net,俺自问不熟,不过俺听说.net里的数据类型不论在32位还是64位,其数据长度都是一样的,并不是你传说中的在32位/64位系统就不同。
[quote]
我都说了.不是指令是64位.是读文件的时候读出的是64位.
就是说在VB6中.你使用GET从一个2进制文件中读一个LONG出来.则在32位系统中读出4个字节.在64位系统中读出8个字节.并不是指令变了.是读出的数据变了.VB6毕竟是解释型 的.GET函数的底层实现可能是使用了系统的API.在32-64两个系统中的API的数据类型字长是不一样的.我已经试过.如果你有任何疑问.请装一个64位操作系统验证后说明.
[/quote]
VB编译的EXE是PE格式的二进制文件,主要内容是指令+操作数让CPU来执行。如果VB6编译器根本不支持64位,它怎么能生成64位的操作数呢?指令的操作数是严格定义好的,怎么可以同一条指令,一下输入32位操作数,一下输入64位操作数让CPU执行呢?
如果“64位系统中读出8个字节”,那为什么在我的x64上还是显示“14131211”呢?
你说的调用API的事,如果我传个32位的数,叫API帮我加1,API怎么会返回一个64位的结果给我呢?如果你还是要坚持,我可以把"Get #1, , ret"的最张实现C代码写给你看:
int ret; //缓冲区,用来接收API返回的读取到的数据
DWORD dwLen; //用来接收API返回的实际读取的字节数
ReadFile(hFile, &ret, sizeof(ret), &dwLen, NULL);
hFile就是文件句柄,在VB里与#1 #2之类的组成一个表,根据VB里的文件号能找到对应的文件句柄。
ret是读取出来的结果,VB编译时已经确定好是32位整数了,所以接下来的sizeof(ret)就是4,也就是告诉API,我只要读4个字节的数据,API怎么会笨到读了8个数据返回给你呢?如果它这样做,肯定是写内存越界了,把ret后面的4字节也写掉了,那软件很可能会出现传说中的“0x040xxxx内存写入读取错误”之类的东西。
实践是很重要,但当你的实践号称推翻“1+1=2”的理论,那只能请你自己检查下“实践”的问题所在。
等你懂点编译原理、懂点汇编语言、懂点组成原理,你再来看下自己说的话,你会觉得很可笑。一辆自行车开到高速公路怎么就变成了大卡车?
[em4][em4][em4]
14 楼
oO羽姿Oo [专家分:600] 发布于 2009-05-21 09:02:00
[quote]很不幸,俺真没亲自试过。不过俺也算科班出身,学过编译原理、操作系统、汇编语言、组成原理、C/C++、VB、Delphi,关于数据长度这点,俺心里还是很清晰的。(指令+操作数编码为不等长二进制,执行时读到内存由CPU译码执行,也就是我前面说的“固化”)
然后又很不幸,俺现在用的是Vista x64 With SP1,也就是你传说中的“64位系统”,所以在你的提示下,俺现在可以写代码亲自试一下。
[code=c]
Option Explicit
Private Const TEMP_FILE As String = "D:\temp.bin"
Private Sub WriteFile()
Dim byt(15) As Byte
Dim i As Long
For i = 1 To 16
byt(i - 1) = &H10 + i
Next
Open TEMP_FILE For Binary Access Write As #1
Put #1, , byt
Close #1
End Sub
[/code]
对于这段,你没有异议吧?我写入的是Byte,不论在哪都一样,最张文件十六进制形式是这样的:
11 12 13 14 15 16 17 18 ...,一共16字节,足够了吧?
[code=c]
Private Sub Read1Long()
Dim ret As Long
Open TEMP_FILE For Binary Access Read As #1
Get #1, , ret
Close #1
MsgBox (Hex(ret))
End Sub
[/code]
很明显,这段是读取一个Long值并用对话框显示的。
OK,让我们调用一下:
[code=c]
Private Sub Form_Load()
WriteFile
Read1Long
Kill TEMP_FILE
End
End Sub
[/code]
写入文件,读取,删除
编译后,在我x64上结果为“14131211”,也就是一个4字节的整数,因为x86兼容的CPU是高位在前的,结果也符合我们事先的预期。
然后,我把这个程序压缩发给使用32位XP的朋友,叫他运行一下发回结果给我。很不幸,结果一样还是“14131211”
如果结果与我事先预期的不一致,那我这么多年真是白学了。
另外要说一下的就是我对VB6的一些理解:VB6已经算是编译型的语言了(除非你特意到编译选项里选择P-Code),它编译的最终结果为Native Code(本地/原生代码),只是很多函数要跳到msvbvm60.dll里面去执行而已。
对于.net,俺自问不熟,不过俺听说.net里的数据类型不论在32位还是64位,其数据长度都是一样的,并不是你传说中的在32位/64位系统就不同。
[quote]
我都说了.不是指令是64位.是读文件的时候读出的是64位.
就是说在VB6中.你使用GET从一个2进制文件中读一个LONG出来.则在32位系统中读出4个字节.在64位系统中读出8个字节.并不是指令变了.是读出的数据变了.VB6毕竟是解释型 的.GET函数的底层实现可能是使用了系统的API.在32-64两个系统中的API的数据类型字长是不一样的.我已经试过.如果你有任何疑问.请装一个64位操作系统验证后说明.
[/quote]
VB编译的EXE是PE格式的二进制文件,主要内容是指令+操作数让CPU来执行。如果VB6编译器根本不支持64位,它怎么能生成64位的操作数呢?指令的操作数是严格定义好的,怎么可以同一条指令,一下输入32位操作数,一下输入64位操作数让CPU执行呢?
如果“64位系统中读出8个字节”,那为什么在我的x64上还是显示“14131211”呢?
你说的调用API的事,如果我传个32位的数,叫API帮我加1,API怎么会返回一个64位的结果给我呢?如果你还是要坚持,我可以把"Get #1, , ret"的最张实现C代码写给你看:
int ret; //缓冲区,用来接收API返回的读取到的数据
DWORD dwLen; //用来接收API返回的实际读取的字节数
ReadFile(hFile, &ret, sizeof(ret), &dwLen, NULL);
hFile就是文件句柄,在VB里与#1 #2之类的组成一个表,根据VB里的文件号能找到对应的文件句柄。
ret是读取出来的结果,VB编译时已经确定好是32位整数了,所以接下来的sizeof(ret)就是4,也就是告诉API,我只要读4个字节的数据,API怎么会笨到读了8个数据返回给你呢?如果它这样做,肯定是写内存越界了,把ret后面的4字节也写掉了,那软件很可能会出现传说中的“0x040xxxx内存写入读取错误”之类的东西。
实践是很重要,但当你的实践号称推翻“1+1=2”的理论,那只能请你自己检查下“实践”的问题所在。
等你懂点编译原理、懂点汇编语言、懂点组成原理,你再来看下自己说的话,你会觉得很可笑。一辆自行车开到高速公路怎么就变成了大卡车?
[em4][em4][em4][/quote]
那我再试一下.有结果了告诉你.至少我上次试的时候读的数据不是你那样的.
呵呵.
15 楼
oO羽姿Oo [专家分:600] 发布于 2009-05-21 09:21:00
如果可以.希望加你QQ一起研究.我有一个程序在两个位宽不同的系统中运行结果不一样.
我现在没有64位系统.希望能帮忙测试.
16 楼
广告专业户 [专家分:400] 发布于 2009-05-21 18:20:00
你打包上传,我看下。
17 楼
oO羽姿Oo [专家分:600] 发布于 2009-05-21 22:18:00
刚才我又装了一个XP-64EDITION.
试了一下.你是对的.
不过.我上次装的时候真的是读出来8个字节.
我是一个一个数据弹出来看的.跟踪后发现每次读的都不是我想要的数据.
但这回装了以后又读的是4字节了....
嗷嗷郁闷中.
我说的那个程序就是网上我发的那个劲舞团舞步提示软件.
那个舞步数据文件就是二进制的.每个步子都是一个LONG值.
以前测试的时候.在32位下运行正确.
但在64位下数据文件加载不了.后来发现是里面的数据读的时候都不对.
但这次我弄过以后又可以加载了.你试试那个软件吧.
感谢"广告专业户"指正错误.我已经把我说错的都删除了.省得误导新手.
64位还有待研究呀.呵呵.
18 楼
襄河渔夫 [专家分:0] 发布于 2009-05-27 10:00:00
谢谢各位大侠指点和讨论!
VB里好像没有int64或_int64数据类型。
我的问题已经解决了,就是定义一个“货币”数据类型(64位)把数据读出,再对小数点位置进行处理就可以了。
19 楼
bcahzvip [专家分:6040] 发布于 2009-05-27 16:18:00
用C做个动态库不行吗?
还是想做个绿色软件?
20 楼
我是大喊三 [专家分:3010] 发布于 2009-05-28 00:15:00
其实VB.NET能定义INT64并不能说它就是编译为64位代码了,变量可以放内存的,连续8个字节.毕竟寄存器数量有限,所以寄存器变量还是很少的,可能编译器会把一些循环变量优先用寄存器.在32位系统,你不可能把64位的数据放进32位的寄存器中.
我来回复