Вы можете использовать each
:
cy.get('p[data-test="ContactID"]').each(($match) => {
cy.wrap($match).invoke('text').should('not.eq', contactID)
})
invoke
для вызова функции на объекте, в данном случае .text()
.should
делает утверждение на этом тексте cy.wrap
Я должен предварять все свои комментарии, говоря, что я все еще учусь правильно.
Я проигнорирую инициализацию раздела. Объяснение инициализации раздела и всего остального, о чем я говорю, можно найти здесь: http://en.wikibooks.org/wiki/X86_Assembly/GAS_Syntax
Регистр ebp является базовым указателем кадра стека , отсюда и BP. Он хранит указатель на начало текущего стека.
Регистр esp является указателем стека. Он содержит ячейку памяти вершины стека. Каждый раз, когда мы помещаем что-то в стек, esp обновляется, так что он всегда указывает на адрес, находящийся на вершине стека.
Таким образом, ebp указывает на базу, а esp указывает на вершину. Итак, стек выглядит так:
esp -----> 000a3 fa
000a4 21
000a5 66
000a6 23
esb -----> 000a7 54
Если вы поместите e4 в стек, вот что произойдет:
esp -----> 000a2 e4
000a3 fa
000a4 21
000a5 66
000a6 23
esb -----> 000a7 54
Обратите внимание, что стек растет в сторону младших адресов, этот факт будет важен ниже.
Первые два шага известны как пролог процедуры или, чаще, пролог функции , они подготавливают стек для использования локальными переменными. pushl% ebp. Поскольку main - это первая вызываемая функция, я не знаю, на что указывает предыдущее значение% ebp.
Шаг 2. Мы вводим новый фрейм стека, потому что мы вводим новую функцию (main). Следовательно, мы должны установить новый указатель базы фрейма стека. Мы используем значение в esp как начало нашего кадра стека.
Шаг 3. Выделяет 8 байтов пространства в стеке. Как мы упоминали выше, стек увеличивается в сторону младших адресов, поэтому при вычитании на 8 верх стека перемещается на 8 байт.
Шаг 4; Выравнивает стек, я нашел разные мнения по этому поводу. Я не совсем уверен, что именно это было сделано. Я подозреваю, что это сделано для того, чтобы разрешить размещение больших инструкций (SIMD) в стеке,
http://gcc.gnu.org/ml/gcc/2008-01/msg00282.html
Этот код "и "s ESP с 0xFFFF0000, выравнивание стека со следующим нижняя 16-байтовая граница. изучение исходного кода Mingw показывает, что это может быть для SIMD инструкции в "_main" процедуры, которые работают только на согласованных адреса. Поскольку наша рутина не содержат инструкции SIMD, эта строка
http://en.wikibooks.org/wiki/X86_Assembly/GAS_Syntax
Шаги с 5 по 11 кажутся мне бесполезными. Я не мог найти объяснения в Google. Может ли кто-нибудь, кто действительно разбирается в этом, глубже понять. До меня доходили слухи, что этот материал используется для обработки исключений C.
Шаг 5 сохраняет возвращаемое значение основного 0 в eax.
На шагах 6 и 7 мы добавляем 15 в шестнадцатеричном формате к eax по неизвестной причине. eax = 01111 + 01111 = 11110
На шаге 8 мы сдвигаем биты eax на 4 бита вправо. eax = 00001, потому что последние биты сдвинуты с конца 00001 | 111.
На шаге 9 мы сдвигаем биты eax на 4 бита влево, eax = 10000.
На шагах 10 и 11 значение в первых 4 выделенных байтах в стеке перемещается в eax, а затем перемещается из eax обратно.
Шаги 12 и 13 устанавливают библиотеку c.
Мы достигли эпилога функции . То есть часть функции, которая возвращает указатели стека, esp и ebp, в состояние, в котором они находились до вызова этой функции.
Шаг 14, leave устанавливает esp на значение ebp, перемещая верх стека в адрес, который был до вызова main. Затем он устанавливает ebp таким образом, чтобы он указывал на адрес, который мы сохранили в верхней части стека на шаге 1.
Leave можно просто заменить следующими инструкциями:
mov %ebp, %esp
pop %ebp
Шаг 15, возврат и выход из функции.
1. pushl %ebp
2. movl %esp, %ebp
3. subl $8, %esp
4. andl $-16, %esp
5. movl $0, %eax
6. addl $15, %eax
7. addl $15, %eax
8. shrl $4, %eax
9. sall $4, %eax
10. movl %eax, -4(%ebp)
11. movl -4(%ebp), %eax
12. call __alloca
13. call ___main
14. leave
15. ret
Процедура Пролог:
Первое, что должна сделать функция перемещение вершины стека по адресу, который был до вызова main. Затем он устанавливает ebp таким образом, чтобы он указывал на адрес, который мы сохранили в верхней части стека на шаге 1.
Leave можно просто заменить следующими инструкциями:
mov %ebp, %esp pop %ebp
Шаг 15, возврат и выход из функции.
1. pushl %ebp 2. movl %esp, %ebp 3. subl $8, %esp 4. andl $-16, %esp 5. movl $0, %eax 6. addl $15, %eax 7. addl $15, %eax 8. shrl $4, %eax 9. sall $4, %eax 10. movl %eax, -4(%ebp) 11. movl -4(%ebp), %eax 12. call __alloca 13. call ___main 14. leave 15. ret
Процедура Пролог:
Первое, что должна сделать функция перемещение вершины стека по адресу, который был до вызова main. Затем он устанавливает ebp таким образом, чтобы он указывал на адрес, который мы сохранили в верхней части стека на шаге 1.
Leave можно просто заменить следующими инструкциями:
mov %ebp, %esp pop %ebp
Шаг 15, возврат и выход из функции.
1. pushl %ebp 2. movl %esp, %ebp 3. subl $8, %esp 4. andl $-16, %esp 5. movl $0, %eax 6. addl $15, %eax 7. addl $15, %eax 8. shrl $4, %eax 9. sall $4, %eax 10. movl %eax, -4(%ebp) 11. movl -4(%ebp), %eax 12. call __alloca 13. call ___main 14. leave 15. ret
Процедура Пролог:
Первое, что должна сделать функция называется прологом процедуры. Это сначала сохраняет текущий базовый указатель (ebp) с инструкцией pushl% ebp (помните, что ebp - это регистр, используемый для доступ к параметрам функции и локальные переменные). Теперь он копирует указатель стека (esp) на базу указатель (ebp) с инструкцией movl% esp,% ebp. Это позволяет вам доступ к параметрам функции как индексы из базового указателя. Местный переменные всегда являются вычитанием от ebp, например -4 (% ebp) или (% ebp) -4 для первой локальной переменной, возвращаемое значение всегда равно 4 (% ebp) или (% ebp) +4, каждый параметр или аргумент равен N * 4 + 4 (% ebp), например 8 (% ebp) для первого аргумента, а старый ebp находится в (% ebp).
http://www.milw0rm.com/papers/52
Существует действительно отличный поток переполнения стека, который отвечает на большую часть этого вопроса. Почему в моем выводе gcc есть лишние инструкции?
Хороший справочник по инструкциям машинного кода x86 можно найти здесь: http://programminggroundup.blogspot.com/2007/01/appendix-b-common-x86-instructions.html
Это лекция, которая содержит некоторые из идей, используемых ниже: http://csc.colstate.edu/bosworth/cpsc5155/Y2006_TheFall/MySlides/CPSC5155_L23.htm
Вот еще один вариант ответа на ваш вопрос: http://www.phiral.net/linuxasmone.htm
Ни один из этих источников не объясняет всего.
Как ни странно, эти шаблоны, похоже, вообще не настраиваются.
Возможно, вы захотите посмотреть этот вопрос . Также этот блог . Google, вероятно, даст вам гораздо больше.
или, возможно, функция ядра, которая вызвала вашу программу)Ну, я не очень разбираюсь в GAS, и я немного заржавел на сборке Intel, но похоже, что он инициализирует основной стек стека.
Если вы посмотрите, __main какой-то макрос должен выполнять инициализации. Затем, поскольку тело main пусто, оно вызывает инструкцию ухода, чтобы вернуться к функции, которая вызвала main.
Из http://en.wikibooks.org/wiki/X86_Assembly/GAS_Syntax#.22hello.s. 22_line-by-line :
В этой строке объявляется метка «_main», обозначающая место, которое вызывается из кода запуска.
pushl %ebp
movl %esp, %ebp
subl $8, %esp
Эти строки сохраняют значение EBP в стеке, а затем перемещают значение ESP в EBP, затем вычтите 8 из ESP. «L» в конце каждого кода операции указывает, что мы хотим использовать версию кода операции, которая работает с «длинными» (32-разрядными) операндами;
andl $-16, %esp
Этот код »и« ESP с 0xFFFF0000, выравнивая стек со следующей нижней 16-байтовой границей. (необходимо при использовании инструкций simd, здесь не полезно)
movl $0, %eax
movl %eax, -4(%ebp)
movl -4(%ebp), %eax
Этот код перемещает ноль в EAX, затем перемещает EAX в ячейку памяти EBP-4, который находится во временном пространстве, которое мы зарезервировали в стеке в начале процедуры. Затем он перемещает ячейку памяти EBP-4 обратно в EAX; очевидно, это не оптимизированный код.
call __alloca
call ___main
Эти функции являются частью настройки библиотеки C. Поскольку мы вызываем функции в библиотеке C, они, вероятно, нам нужны. Точные операции, которые они выполняют, различаются в зависимости от платформы и версии установленных инструментов GNU.
Вот полезная ссылка.
Похоже, что GCC действует так, как будто можно отредактировать main ()
, чтобы включить код инициализации CRT. Я только что подтвердил, что я получаю точно такой же лист сборки из MinGW GCC 3.4.5 здесь, с вашим исходным текстом.
Командная строка, которую я использовал:
gcc -S emptymain.c
Интересно, если я изменю имя функции на qqq ()
вместо main ()
, я получаю следующую сборку:
.file "emptymain.c" .text .globl _qqq .def _qqq; .scl 2; .type 32; .endef _qqq: pushl %ebp movl %esp, %ebp popl %ebp ret
, которая имеет гораздо больше смысла для пустой функции без включенной оптимизации.
It would really help to know what gcc version you are using and what libc. It looks like you have a very old gcc version or a strange platform or both. What's going on is some strangeness with calling conventions. I can tell you a few things:
Save the frame pointer on the stack according to convention:
pushl %ebp
movl %esp, %ebp
Make room for stuff at the old end of the frame, and round the stack pointer down to a multiple of 4 (why this is needed I don't know):
subl $8, %esp
andl $-16, %esp
Through an insane song and dance, get ready to return 1 from main
:
movl $0, %eax
addl $15, %eax
addl $15, %eax
shrl $4, %eax
sall $4, %eax
movl %eax, -4(%ebp)
movl -4(%ebp), %eax
Recover any memory allocated with alloca
(GNU-ism):
call __alloca
Announce to libc that main
is exiting (more GNU-ism):
call ___main
Restore the frame and stack pointers:
leave
Return:
ret
Here's what happens when I compile the very same source code with gcc 4.3 on Debian Linux:
.file "main.c"
.text
.p2align 4,,15
.globl main
.type main, @function
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ecx
popl %ecx
popl %ebp
leal -4(%ecx), %esp
ret
.size main, .-main
.ident "GCC: (Debian 4.3.2-1.1) 4.3.2"
.section .note.GNU-stack,"",@progbits
And I break it down this way:
Tell the debugger and other tools the source file:
.file "main.c"
Code goes in the text section:
.text
Beats me:
.p2align 4,,15
main
is an exported function:
.globl main
.type main, @function
main
's entry point:
main:
Grab the return address, align the stack on a 4-byte address, and save the return address again (why I can't say):
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
Save frame pointer using standard convention:
pushl %ebp
movl %esp, %ebp
Inscrutable madness:
pushl %ecx
popl %ecx
Restore the frame pointer and the stack pointer:
popl %ebp
leal -4(%ecx), %esp
Return:
ret
More info for the debugger?:
.size main, .-main
.ident "GCC: (Debian 4.3.2-1.1) 4.3.2"
.section .note.GNU-stack,"",@progbits
By the way, main
is special and magical; when I compile
int f(void) {
return 17;
}
I get something slightly more sane:
.file "f.c"
.text
.p2align 4,,15
.globl f
.type f, @function
f:
pushl %ebp
movl $17, %eax
movl %esp, %ebp
popl %ebp
ret
.size f, .-f
.ident "GCC: (Debian 4.3.2-1.1) 4.3.2"
.section .note.GNU-stack,"",@progbits
There's still a ton of decoration, and we're still saving the frame pointer, moving it, and restoring it, which is utterly pointless, but the rest of the code make sense.